Java Stream中的API你都用过了吗?

公众号「架构成长指南」,专注于生产实践、云原生、分布式系统、大数据技术分享。

在本教程中,您将通过大量示例来学习 Java 8 Stream API。

Java 在 Java 8 中提供了一个新的附加包,称为 java.util.stream。该包由类、接口和枚举组成,允许对元素进行函数式操作。 您可以通过在程序中导入 java.util.stream包来使用流。

Stream提供以下功能:

Stream不存储元素。它只是通过计算操作的管道传送来自数据结构、数组或 I/O 通道等源的元素。

Stream本质上是函数式的,对流执行的操作不会修改其源。例如,过滤从集合获取的 Stream 会生成一个没有过滤元素的新 Stream,而不是从源集合中删除元素。

Stream是惰性的,仅在需要时才计算代码,在流的生命周期中,流的元素仅被访问一次。

与迭代器一样,必须生成新流才能重新访问源中的相同元素。
您可以使用 Stream 来 过滤、收集、打印以及 从一种数据结构转换为其他数据结构等。

Stream API 示例

1. 创建一个空的Stream

在创建空流时,应使用 empty() 方法:

Stream<String> stream = Stream.empty();
stream.forEach(System.out::println);

通常情况下,在创建时会使用 empty() 方法,以避免在没有元素的流中返回 null:

public Stream<String> streamOf(List<String> list) {
    return list == null || list.isEmpty() ? Stream.empty() : list.stream();
}
2.从集合中创建流
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;

public class StreamCreationExamples {
    public static void main(String[] args) throws IOException {

        Collection<String> collection = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
        Stream<String> stream2 = collection.stream();
        stream2.forEach(System.out::println);

        List<String> list = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
        Stream<String> stream3 = list.stream();
        stream3.forEach(System.out::println);

        Set<String> set = new HashSet<>(list);
        Stream<String> stream4 = set.stream();
        stream4.forEach(System.out::println);
    }
}

输出

JAVA
J2EE
Spring
Hibernate
JAVA
J2EE
Spring
Hibernate
JAVA
Hibernate
J2EE
Spring
3. 从数组中创建流对象

数组可以是流的源,也可以从现有数组或数组的一部分创建数组:

import java.util.Arrays;
import java.util.stream.Stream;

public class StreamCreationExample {
    public static void main(String[] args) {
        // 使用Arrays.stream()创建流
        int[] numbers = {1, 2, 3, 4, 5};
        Stream<Integer> stream1 = Arrays.stream(numbers);
        System.out.println("Using Arrays.stream():");
        stream1.forEach(System.out::println);

        // 使用Stream.of()创建流
        String[] names = {"Alice", "Bob", "Charlie"};
        Stream<String> stream2 = Stream.of(names);
        System.out.println("Using Stream.of():");
        stream2.forEach(System.out::println);

        // 使用Stream.builder()创建流
        String[] colors = {"Red", "Green", "Blue"};
        Stream.Builder<String> builder = Stream.builder();
        for (String color : colors) {
            builder.add(color);
        }
        Stream<String> stream3 = builder.build();
        System.out.println("Using Stream.builder():");
        stream3.forEach(System.out::println);
    }
}

输出

Using Arrays.stream():
1
2
3
4
5
Using Stream.of():
Alice
Bob
Charlie
Using Stream.builder():
Red
Green
Blue
4. 使用Stream过滤一个集合示例

在下面的示例中,我们不使用流过滤数据,看看代码是什么样的,同时我们在给出一个使用stream过滤的示例,对比一下

不使用Stream过滤一个集合示例

import java.util.ArrayList;
import java.util.List;

public class FilterWithoutStreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);
        numbers.add(50);

        List<Integer> filteredNumbers = new ArrayList<>();
        for (Integer number : numbers) {
            if (number > 30) {
                filteredNumbers.add(number);
            }
        }

        System.out.println("Filtered numbers (without Stream):");
        for (Integer number : filteredNumbers) {
            System.out.println(number);
        }
    }
}

输出:

Filtered numbers (without Stream):
40
50

使用 Stream 过滤集合示例:

import java.util.ArrayList;
import java.util.List;

public class FilterWithStreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);
        numbers.add(50);

        List<Integer> filteredNumbers = numbers.stream()
                .filter(number -> number > 30)
                .toList();

        System.out.println("Filtered numbers (with Stream):");
        filteredNumbers.forEach(System.out::println);
    }
}

输出:

Filtered numbers (with Stream):
40
50

前后我们对比一下,可以看到,使用 Stream 进行集合过滤可以更加简洁和直观,减少了手动迭代和添加元素的步骤。它提供了一种声明式的编程风格,使代码更易读、可维护和可扩展。

5. 使用Stream过滤和遍历集合

在下面的示例中,我们使用 filter() 方法进行过滤,使用 forEach() 方法对数据流进行迭代:

import java.util.ArrayList;
import java.util.List;

public class FilterAndIterateWithStreamExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Charlie");
        names.add("David");
        names.add("Eve");

        System.out.println("Filtered names starting with 'A':");
        names.stream()
                .filter(name -> name.startsWith("A"))
                .forEach(System.out::println);
    }
}

输出

Filtered names starting with 'A':
Alice

在上述示例中,我们有一个字符串列表 names,其中包含了一些名字。
我们使用 Stream 进行过滤和迭代操作以查找以字母 “A” 开头的名字。

6.使用Collectors方法求和

我们还可以使用Collectors计算数值之和。

在下面的示例中,我们使用Collectors类及其指定方法计算所有产品价格的总和。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class SumByUsingCollectorsMethods {
    public static void main(String[] args) {
        List < Product > productsList = new ArrayList < Product > ();
        productsList.add(new Product(1, "HP Laptop", 25000f));
        productsList.add(new Product(2, "Dell Laptop", 30000f));
        productsList.add(new Product(3, "Lenevo Laptop", 28000f));
        productsList.add(new Product(4, "Sony Laptop", 28000f));
        productsList.add(new Product(5, "Apple Laptop", 90000f));
        
        double totalPrice3 = productsList.stream()
            .collect(Collectors.summingDouble(product -> product.getPrice()));
        System.out.println(totalPrice3);

    }
}

输出

201000.0
7. 使用Stream查找年龄最大和最小的学生

假设有一个 Student 类具有 name 和 age 属性。我们可以使用 Stream 来查找学生集合中年龄的最大和最小值,并打印出相应的学生信息。以下是一个示例:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

public class StudentStreamExample {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 20));
        students.add(new Student("Bob", 22));
        students.add(new Student("Charlie", 19));
        students.add(new Student("David", 21));

        // 查找年龄最大的学生
        Optional<Student> maxAgeStudent = students.stream()
                .max(Comparator.comparingInt(Student::getAge));

        // 查找年龄最小的学生
        Optional<Student> minAgeStudent = students.stream()
                .min(Comparator.comparingInt(Student::getAge));

        // 打印最大和最小年龄的学生信息
        System.out.println("Student with maximum age:");
        maxAgeStudent.ifPresent(System.out::println);

        System.out.println("Student with minimum age:");
        minAgeStudent.ifPresent(System.out::println);
    }
}

class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

输出:

Student with maximum age:
Student{name='Bob', age=22}
Student with minimum age:
Student{name='Charlie', age=19}
8. 使用Stream转换List为Map
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class StudentStreamToMapExample {
    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("Alice", 20));
        students.add(new Student("Bob", 22));
        students.add(new Student("Charlie", 19));
        students.add(new Student("David", 21));

        // 将学生列表转换为 Map,以姓名为键,学生对象为值
        Map<String, Student> studentMap = students.stream()
                .collect(Collectors.toMap(Student::getName, student -> student));

        // 打印学生 Map
        for (Map.Entry<String, Student> entry : studentMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }
}

class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

输出

David: Student{name='David', age=21}
Bob: Student{name='Bob', age=22}
Charlie: Student{name='Charlie', age=19}
Alice: Student{name='Alice', age=20}

在上面示例中,我们使用Collectors.toMap() 方法将学生列表转换为 Map。我们指定了键提取器 Student::getName,将学生的姓名作为键。对于值提取器,我们使用了一个匿名函数 student -> student,它返回学生对象本身作为值。

9. 使用Stream把List对象转换为另一个List对象

假设我们有一个 Person 类,其中包含姓名和年龄属性。我们可以使用 Stream 来将一个 List 对象转换为另一个 List 对象,其中只包含人员的姓名。以下是一个示例:

  import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ListTransformationExample {
    public static void main(String[] args) {
        List<Person> persons = new ArrayList<>();
        persons.add(new Person("Alice", 20));
        persons.add(new Person("Bob", 22));
        persons.add(new Person("Charlie", 19));

        // 将 Person 列表转换为只包含姓名的 String 列表
        List<String> names = persons.stream()
                .map(Person::getName)
                .collect(Collectors.toList());

        // 打印转换后的姓名列表
        System.out.println(names);
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

输出:

  [Alice, Bob, Charlie]

在上述示例中,我们有一个 Person 类,其中包含姓名和年龄属性。我们创建了一个 persons 列表,并添加了几个 Person 对象。

使用Stream,我们通过调用 map() 方法并传入一个方法引用 Person::getName,最后,我们使用 collect() 方法和 Collectors.toList() 将转换后的姓名收集到一个新的列表中。

API

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/176786.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

netstat

netstat 命令用于显示网络状态 参数说明&#xff1a; -a或--all 显示所有连线中的Socket&#xff0c;默认不显示LISTEN相关 -n 拒绝显示别名&#xff0c;能显示数字的全部转化成数字 -e或--extend 显示网络扩展信息(User&#xff0c;Inode) -p或--programs 显示正在使用So…

【精选】构建智能木材计数系统:深度学习与OpenCV完美结合(详细教程+源码)

1.研究背景与意义 随着科技的不断发展&#xff0c;计算机视觉技术在各个领域中得到了广泛的应用。其中&#xff0c;卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;CNN&#xff09;作为一种强大的深度学习模型&#xff0c;已经在图像识别、目标检测、人脸识…

Linux常用操作 Vim一般使用 SSH介绍 SSH密钥登录

目录 1. 常用命令 2. vim一般使用 3. SSH介绍 4. ssh密钥登录 1. 常用命令 1&#xff09;# 与 $ 提示的区别 # 表示用户有root权限&#xff0c;一般的以root用户登录提示符为#&#xff0c; $提示符表示用户为普通用户 2&#xff09;ifconfig 查看ip地址 eno1: 代表由主板…

【React-Router】导航传参

1. searchParams 传参 // /page/Login/index.js import { Link, useNavigate } from react-router-dom const Login () > {const navigate useNavigate()return <div>登录页<button onClick{() > navigate(/article?id91&namejk)}>searchParams 传参…

永恒之蓝漏洞复现

https://blog.csdn.net/qq_44159028/article/details/104044002 跟着这篇复现的 改造“永恒之蓝”制作了wannacry勒索病毒&#xff0c;使全世界大范围内遭受了该勒索病毒 影响版本 目前已知受影响的 Windows 版本包括但不限于&#xff1a;WindowsNT&#xff0c;Windows2000、W…

普乐蛙VR航天航空巡展项目来到了第七站——绵阳科博会

Hi~ 你有一份邀约请查收 11月22日—26日绵阳科博会 普乐蛙展位号&#xff1a;B馆科技体验区(1) 邀你体验趣味VR科普&#xff0c;探索科技新发展 第十一届中国(绵阳)科技城国际科技博览会 绵阳科博会自2013年创办以来&#xff0c;已连续成功举办十届&#xff0c;已有近7000家单位…

PostgreSQL导出表结构带注释

我们在平时开发过程中&#xff0c;经常会在字段的注释中&#xff0c;加上中文&#xff0c;解释字段的相关含义&#xff0c;也可以避免时间太久忘记这个字段代表什么&#xff0c;毕竟英文水平不好。我们可能要经常整理数据库表结构&#xff0c;提供他人去收集数据&#xff0c;但…

运行代码时不同软件的参数写法

目录 pycharm终端 pycharm 如下图所示&#xff0c;不同参数间不需要什么间隔什么东西 终端 如下图所示&#xff0c;不同参数间需要用一个符号来间隔

企业如何选择一款高效的ETL工具

企业如何选择一款高效的ETL工具? 在企业发展至一定规模后&#xff0c;构建数据仓库&#xff08;Data Warehouse&#xff09;和商业智能&#xff08;BI&#xff09;系统成为重要举措。在这个过程中&#xff0c;选择一款易于使用且功能强大的ETL平台至关重要&#xff0c;因为数…

2023 IDEA大会开幕 共探AI新篇章下的技术创新与创业

11月22日&#xff0c;AI与数字经济领域一年一度的科创盛会&#xff0c;2023 IDEA大会在深圳举行。IDEA研究院创院理事长、美国国家工程院外籍院士沈向洋在会上发表主旨演讲&#xff0c;发布IDEA研究院的重磅研产结晶与市场化成果&#xff1b;在大咖云集的论坛环节&#xff0c;多…

除夕不放假HR如何做

国务院办公厅发布了 关于2024年部分节假日安排的通知 全文如下 各省、自治区、直辖市人民政府&#xff0c;国务院各部委、各直属机构&#xff1a; 经国务院批准&#xff0c;现将2024年元旦、春节、清明节、劳动节、端午节、中秋节和国庆节放假调休日期的具体安排通知如下。 …

Grafana Panel组件跳转、交互实现

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

提升企业人效,从精细化考勤管理开始

过去&#xff0c;许多企业提到考勤管理&#xff0c;只能关联到打卡、请假、算薪这些简单的事务性流程。随着越来越多企业希望通过数字化转型来提升运营效率&#xff0c;实现精细化人员管理。考勤数据的作用也不再仅限于算薪&#xff0c;而是成为了企业分析人效的关键因子。因此…

SQLite3 数据库学习(四):Qt 数据库基础操作

参考引用 SQLite 权威指南&#xff08;第二版&#xff09;SQLite3 入门 1. 创建连接执行 sql 语句 在 Qt 中使用数据库要在工程文件中添加QT sql1.1 main.cpp #include "createsqlapp.h" #include <QApplication> #include <QSqlDatabase> #include &l…

埃森哲使用 Amazon CodeWhisperer 助力开发人员提高工作效率

Amazon CodeWhisperer 是一款 AI 编程助手&#xff0c;可根据开发人员使用自然语言编写的注释和 IDE&#xff08;集成开发环境&#xff09;中的代码生成建议&#xff0c;帮助开发人员提高工作效率。借助 CodeWhisperer&#xff0c;开发人员无需在 IDE 与文档或开发者论坛之间切…

③【List】Redis常用数据类型: List [使用手册]

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Redis List ③Redis List 操作命令汇总1. lpus…

UVA11584划分成回文串 Partitioning by Palindromes

划分成回文串 Partitioning by Palindromes 题面翻译 回文子串(palind) 问题描述&#xff1a; 当一个字符串正序和反序是完全相同时&#xff0c;我们称之为“回文串”。例如“racecar”就是一个回文串&#xff0c;而“fastcar”就不是。现在给一个字符串s&#xff0c;把它分…

坚鹏:湖北银行数字化转型背景下银行运营管理创新培训圆满结束

湖北银行正式成立于2011年2月27日&#xff0c;总部设在武汉。现有员工5000余人。营业网点从成立之初的93家增长至241家&#xff0c;实现全省17个市州、59个县域营业网点全覆盖。截至2022年末&#xff0c;全行资产总额4026亿元&#xff0c;存款总额2956亿元&#xff0c;贷款总额…

怎样实现内网穿透?

第一步&#xff1a;cpolar是一种安全的内网穿透云服务&#xff0c;它将内网下的本地服务器通过安全隧道暴露至公网。使得公网用户可以正常访问内网服务。打开网址 cpolar 下载 。 步骤&#xff1a; 打开网站>点击免费试用>创建账号>下载应用一直点下一步下载完成。第…