9张图,32个案例带你轻松玩转Java stream(下)

简介: 9张图,32个案例带你轻松玩转Java stream

4 短路操作

微信图片_20221213105518.png

4.1 findAny

找出 stream 中任何一个满足过滤条件的元素。

案例 14:找出任何一个成绩高于 90 分的学生

List<Student> students = new ArrayList<>();
students.add(new Student("Mike", 10, "male", 88));
students.add(new Student("Jack", 13,"male", 90));
students.add(new Student("Lucy", 15,"female", 100));
students.add(new Student("Jessie", 12,"female", 78));
students.add(new Student("Allon", 16,"female", 92));
students.add(new Student("Alis", 22,"female", 50));
Optional<Student> studentFindAny = students.stream().filter(x -> x.getScore() > 90).findAny();
System.out.print("找出任意一个考试成绩在90分以上的学生姓名:" + studentFindAny.orElseGet(null).getName());

输出结果:

找出任意一个考试成绩在90分以上的学生姓名:Lucy

4.2 anyMatch

是否存在任意一个满足给定条件的元素。

案例 15:是否存在成绩高于 90 分的学生,是否存在成绩低于 50 分的学生。还是采用上面案例 14 中的学生集合。

boolean result1 = students.stream().anyMatch(x -> x.getScore() > 90);
System.out.println("是否存在成绩高于 90 分的学生:" + result1);
boolean result2 = students.stream().anyMatch(x -> x.getScore() < 50);
System.out.print("是否存在成绩低于 50 分的学生:" + result2);

输出结果:

是否存在成绩高于 90 分的学生:true

是否存在成绩低于 50 分的学生:false

4.3 allMatch

是否集合中所有元素都满足给定的条件,如果集合是空,则返回 true。

案例 16:学生成绩是否都高于 90 分,是否都高于 50 分。还是采用上面案例 14 中的学生集合。

boolean result1 = students.stream().allMatch(x -> x.getScore() > 90);
System.out.println("是否所有学生的成绩都高于90分:" + result1);
boolean result2 = students.stream().allMatch(x -> x.getScore() > 50);
System.out.print("是否所有学生的成绩都高于50分:" + result2);

输出结果:

是否所有学生的成绩都高于90分:false

是否所有学生的成绩都高于50分:true

4.4 noneMatch

是否没有元素能匹配给定的条件,如果集合是空,则返回 true。

案例 17:是不是没有学生成绩在 90 分以上,是否没有学生成绩在 50 分以下。还是采用上面案例 14 中的学生集合。

boolean result1 = students.stream().noneMatch(x -> x.getScore() > 90);
System.out.println("是不是没有学生成绩在 90 分以上:" + result1);
boolean result2 = students.stream().noneMatch(x -> x.getScore() < 50);
System.out.print("是不是没有学生成绩在 50 分以下:" + result2);

输出结果:

是不是没有学生成绩在 90 分以上:false

是不是没有学生成绩在 50 分以下:true

4.5 findFirst

找出第一个符合条件的元素。

案例 18:找出第一个成绩在 90 分以上的学生。还是采用上面案例 14 中的学生集合。

Optional<Student> studentFindAny = students.stream().filter(x -> x.getScore() > 90).findFirst();
System.out.print("第一个成绩在 90 分以上的学生姓名:" + studentFindAny.orElseGet(null).getName());

输出结果:

第一个成绩在 90 分以上的学生姓名:Lucy

5 非短路操作

微信图片_20221213105557.png

5.1 forEach

遍历元素。

案例 19:遍历一个数组并打印

List<Integer> array = Arrays.asList(5, 2, 3, 1, 4);
array.stream().forEach(System.out :: println);

输出结果:

5 2 3 1 4

5.2 forEachOrdered

按照给定集合中元素的顺序输出。主要使用场景是在并行流的情况下,按照给定的顺序输出元素。

案例 20:用并行流遍历一个数组并按照给定数组的顺序输出结果

List<Integer> array = Arrays.asList(5, 2, 3, 1, 4);
array.parallelStream().forEachOrdered(System.out :: println);

输出结果:

5 2 3 1 4

5.3 toArray

返回包括给定 stream 中所有元素的数组。

案例 21:把给定字符串流转化成数组

Stream<String> stream = Arrays.asList("ab", "abc", "abcd", "abcde", "abcdef").stream();
String[] newArray1 = stream.toArray(str -> new String[5]);
String[] newArray2 = stream.toArray(String[]::new);
Object[] newArray3 = stream.toArray();

5.4 reduce

规约操作,把一个流的所有元素合并成一个元素,比如求和、求乘积、求最大最小值等。

案例 22:求整数数组元素之和、乘积和最大值

List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);
Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
Optional<Integer> product = list.stream().reduce((x, y) -> x * y);
Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
System.out.println("数组元素之和:" + sum.get());
System.out.println("数组元素乘积:" + product.get());
System.out.println("数组元素最大值:" + max.get());

输出结果:

数组元素之和:15

数组元素乘积:120

数组元素最大值:5

案例 23:求全班学生最高分、全班学生总分

List<Student> students = new ArrayList<>();
students.add(new Student("Mike", 10, "male", 88));
students.add(new Student("Jack", 13,"male", 90));
students.add(new Student("Lucy", 15,"female", 100));
students.add(new Student("Jessie", 12,"female", 78));
students.add(new Student("Allon", 16,"female", 92));
students.add(new Student("Alis", 22,"female", 50));
Optional<Integer> maxScore = students.stream().map(r -> r.getScore()).reduce(Integer::max);
Optional<Integer> sumScore = students.stream().map(r -> r.getScore()).reduce(Integer::sum);
System.out.println("全班学生最高分:" + maxScore.get());
System.out.println("全班学生总分:" + sumScore.get());

输出结果:

全班学生最高分:100

全班学生总分:498

5.5 collect

把 stream 中的元素归集到新的集合或者归集成单个元素。

5.5.1 归集成新集合

方法包括 toList、toSet、toMap。

案例 24:根据学生列表,归纳出姓名列表、不同分数列表、姓名分数集合,其中 Mike 和 Jessie 的分数都是 88。

List<Student> students = new ArrayList<>();
students.add(new Student("Mike", 10, "male", 88));
students.add(new Student("Jack", 13,"male", 90));
students.add(new Student("Lucy", 15,"female", 100));
students.add(new Student("Jessie", 12,"female", 88));
students.add(new Student("Allon", 16,"female", 92));
students.add(new Student("Alis", 22,"female", 50));
List<String> list = students.stream().map(r -> r.getName()).collect(Collectors.toList());
Set<Integer> set = students.stream().map(r -> r.getScore()).collect(Collectors.toSet());
Map<String, Integer> map = students.stream().collect(Collectors.toMap(Student::getName, Student::getScore));
System.out.println("全班学生姓名列表:" + list);
System.out.println("全班学生不同分数列表:" + set);
System.out.println("全班学生姓名分数集合:" + map);

输出结果:

全班学生姓名列表:[Mike, Jack, Lucy, Jessie, Allon, Alis]

全班学生不同分数列表:[50, 100, 88, 90, 92]

全班学生姓名分数集合:{Mike=88, Allon=92, Alis=50, Lucy=100, Jack=90, Jessie=88}

5.5.2 统计功能

微信图片_20221213105628.png

统计功能包括如下方法:

微信图片_20221213105658.png

案例 25:求总数、求和、最大/最小/平均值

List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);
long count = list.stream().collect(Collectors.counting());
int sum = list.stream().collect(Collectors.summingInt(r -> r));
double average = list.stream().collect(Collectors.averagingDouble(r -> r));
Optional<Integer> max = list.stream().collect(Collectors.maxBy(Integer::compare));
Optional<Integer> min = list.stream().collect(Collectors.maxBy((x, y) -> x > y ? y : x));
System.out.println("总数:" + count);
System.out.println("总和:" + sum);
System.out.println("平均值:" + average);
System.out.println("最大值:" + max.get());
System.out.println("最小值:" + min.get());

输出结果:

总数:5

总和:15

平均值:3.0

最大值:5

最小值:5

案例 26:求总和统计

List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);
IntSummaryStatistics statistics = list.stream().collect(Collectors.summarizingInt(r -> r));
System.out.println("综合统计结果:" + statistics.toString());

输出结果:

综合统计结果:IntSummaryStatistics{count=5, sum=15, min=1, average=3.000000, max=5}

5.5.3 分区和分组

主要包括两个函数:

  • partitioningBy:把 stream 分成两个 map
  • groupingBy:把 stream 分成多个 map

案例 27:将学生按照 80 分以上和以下分区

List<Student> students = new ArrayList<>();
students.add(new Student("Mike", 10, "male", 88));
students.add(new Student("Jack", 10,"male", 90));
students.add(new Student("Lucy", 12,"female", 100));
students.add(new Student("Jessie", 12,"female", 78));
students.add(new Student("Allon", 16,"female", 92));
students.add(new Student("Alis", 16,"female", 50));
Map<Boolean, List<Student>> partitionByScore = students.stream().collect(Collectors.partitioningBy(x -> x.getScore() > 80));
System.out.println("将学生按照考试成绩80分以上分区:");
partitionByScore.forEach((k,v ) -> {
    System.out.print(k ? "80分以上:" : "80分以下:");
    v.forEach(r -> System.out.print(r.getName() + ","));
    System.out.println();
});
System.out.println();

分区结果是把 Student 列表分成 key 只有 true 和 false 两个值的 map,输出如下:

将学生按照考试成绩80分以上分区:

80分以下:Jessie,Alis,

80分以上:Mike,Jack,Lucy,Allon,

案例 28:将学生按照性别、年龄分组

Map<String, Map<Integer, List<Student>>> group = students.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getAge)));
System.out.println("将学生按照性别、年龄分组:");
group.forEach((k,v ) -> {
    System.out.println(k +":");
    v.forEach((k1,v1) -> {
        System.out.print("      " + k1 + ":" );
        v1.forEach(r -> System.out.print(r.getName() + ","));
        System.out.println();
    });
});

输出如下:

将学生按照性别、年龄分组:

female:

     16:Allon,Alis,

     12:Lucy,Jessie,

male:

     10:Mike,Jack,

5.5.4 连接

将 stream 中的元素用指定的连接符合并,连接符可以是空。

案例 29:输出所有学生的姓名,用逗号分隔,这里还是使用案例 27 中的学生列表

String studentNames = students.stream().map(r -> r.getName()).collect(Collectors.joining(","));
System.out.println("所有学生姓名列表:" + studentNames);

输出如下:

所有学生姓名列表:Mike,Jack,Lucy,Jessie,Allon,Alis

5.5.5 规约

在 5.4 节已经讲过规约了,这里的规约支持更强大的自定义规约。

案例 30:数组中每个元素加 1 后求总和

List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);
int listSum = list.stream().collect(Collectors.reducing(0, x -> x + 1, (sum, b) -> sum + b));
System.out.println("数组中每个元素加 1 后总和:" + listSum);

输出结果:

数组中每个元素加 1 后总和:20

5.6 max、min、count

stream 提供的方便统计的方法。

案例 31:统计整数数组中最大值、最小值、大于 3 的元素个数

List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);
System.out.println("数组元素最大值:"+list.stream().max(Integer::compareTo).get());
System.out.println("数组元素最小值:"+list.stream().min(Integer::compareTo).get());
System.out.println("数组中大于3的元素个数:"+list.stream().filter(x -> x > 3).count());

输出结果:

数组元素最大值:5

数组元素最小值:1

数组中大于3的元素个数:2

案例 32:统计分数最高的学生姓名

List<Student> students = new ArrayList<>();
students.add(new Student("Mike", 10, "male", 88));
students.add(new Student("Jack", 10,"male", 90));
students.add(new Student("Lucy", 12,"female", 100));
students.add(new Student("Jessie", 12,"female", 78));
students.add(new Student("Allon", 16,"female", 92));
students.add(new Student("Alis", 16,"female", 50));
Optional<Student> optional = students.stream().max(Comparator.comparing(r -> r.getScore()));
System.out.println("成绩最高的学生姓名:" + optional.get().getName());

输出结果:

成绩最高的学生姓名:Lucy

       ··············  END  ··············

相关文章
|
26天前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
42 6
|
26天前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
17天前
|
Rust 安全 Java
Java Stream 使用指南
本文介绍了Java中Stream流的使用方法,包括如何创建Stream流、中间操作(如map、filter、sorted等)和终结操作(如collect、forEach等)。此外,还讲解了并行流的概念及其可能带来的线程安全问题,并给出了示例代码。
|
1月前
|
jenkins Java 测试技术
如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例详细说明
本文介绍了如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例,详细说明了从 Jenkins 安装配置到自动构建、测试和部署的全流程。文中还提供了一个 Jenkinsfile 示例,并分享了实践经验,强调了版本控制、自动化测试等关键点的重要性。
73 3
|
28天前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
26 0
|
1月前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
69 2
|
1月前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
38 2
|
1月前
|
Java API 数据处理
探索Java中的Lambda表达式与Stream API
【10月更文挑战第22天】 在Java编程中,Lambda表达式和Stream API是两个强大的功能,它们极大地简化了代码的编写和提高了开发效率。本文将深入探讨这两个概念的基本用法、优势以及在实际项目中的应用案例,帮助读者更好地理解和运用这些现代Java特性。
|
2月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
25 1
|
2月前
|
Java API 数据处理
java Stream详解
【10月更文挑战第4天】
41 0