Java stream流式计算详解

  • 1. Stream概述
    • 1.1 Stream简介
    • 1.2 Stream分类
  • 2. Stream操作
    • 2.1 Stream创建
    • 2.2 Stream无状态操作
    • 2.3 Stream有状态操作
    • 2.4 Stream短路操作
    • 2.5 Stream非短路操作
  • 3. 测试验证

1. Stream概述

1.1 Stream简介

对于Java8提供的Stream与Lambda表达式结合使用的功能,每个人看法不一,这种语法糖操作确实带来了一定的便利,使代码更加的简洁,但同时也在降低代码的可读性,代码是给人读的不只是机器运行的,所以具体使用看个人的接受程度以及书写风格了。

1.2 Stream分类

Stream 提供的方法非常多,按照调用当前方法是否结束流处理,可以分为中间操作和结束操作。

对于中间操作,又可以分为有状态的操作和无状态操作:
1.无状态的操作是指当前元素的操作不受前面元素的影响。
2.有状态的操作是指当前元素的操作需要等所有元素处理完之后才能进行。

对于结束操作,又可以分为短路操作和非短路操作,具体如下:
1.短路操作是指不需要处理完全部的元素就可以结束。
2.非短路操作是指必须处理完所有元素才能结束。

Stream无状态操作:map,mapToXXX,flatMap,flatMapToXXX,filter,peek,unordered
Stream有状态操作:distinct,limit,skip,sorted
Stream短路操作:findAny,anyMatch,allMatch,noneMatch,findFirst
Stream非短路操作:forEach,forEachOrdered,toArray,reduce,collect,max、min、count

2. Stream操作

2.1 Stream创建

Stream创建:使用集合创建,使用数组创建,使用 Stream 静态方法

    /*** 1.创建Stream* 1.1 使用集合创建* 1.2 使用数组创建* 1.3 使用 Stream 静态方法*/@Testpublic void createStream() {//1.1使用集合创建List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);Stream streamInt = list.stream();printStream(streamInt, "1.1使用集合创建Stream:");System.out.println("-----------------------");//1.2使用数组创建String[] array = {"ab", "abc", "abcd", "abcde", "abcdef"};Stream<String> streamStr = Arrays.stream(array);printStream(streamStr, "1.2使用数组创建Stream:");System.out.println("-----------------------");//1.3使用 Stream 静态方法Stream<String> streamStatic = Stream.of("ab", "abc", "abcd", "abcde", "abcdef");printStream(streamStatic, "1.3使用 Stream 静态方法Stream:");System.out.println("-----------------------");Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 3).limit(5);printStream(stream4, "Stream迭代器:");Stream<Integer> stream5 = Stream.generate(new Random()::nextInt).limit(3);printStream(stream5, "Stream构建器:");System.out.println("-----------------------");}

2.2 Stream无状态操作

Stream无状态操作:map,mapToXXX,flatMap,flatMapToXXX,filter,peek,unordered

/*** 2.Stream无状态操作* 2.1 map* 2.2 mapToXXX* 2.3 flatMap* 2.4 flatMapToXXX* 2.5 filter* 2.6 peek* 2.7 unordered*/@Testpublic void operationStreamStateless() {//2.1 map,接收一个函数作为入参,把这个函数应用到每个元素上,执行结果组成一个新的 stream 返回。//案例1:对整数数组每个元素加3 :List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);List<Integer> newList = list.stream().map(x -> x + 3).collect(Collectors.toList());System.out.println("案例1:对整数数组每个元素加3的值:" + newList);//案例2:把字符串数组的每个元素转换为大写:List<String> listStr = Arrays.asList("ab", "abc", "abcd", "abcde", "abcdef");List<String> newListStr = listStr.stream().map(String::toUpperCase).collect(Collectors.toList());System.out.println("案例2:把字符串数组的每个元素转换为大写:" + newListStr);System.out.println("-----------------------");//2.2 mapToXXX,包括三个方法:mapToInt、mapToDouble、mapToLong//案例3:把字符串数组转为整数数组:List<String> listStr3 = Arrays.asList("ab", "abc", "abcd", "abcde", "abcdef");int[] newList3 = listStr3.stream().mapToInt(r -> r.length()).toArray();System.out.println("案例3:把字符串数组转为整数数组: " + Arrays.toString(newList3));System.out.println("-----------------------");//2.3 flatMap,flatMap接收函数作为入参,然后把集合中每个元素转换成一个stream,再把这些stream组成一个新的stream,是拆分单词很好的工具。//案例4:把一个字符串数组转成另一个字符串数组:List<String> list4 = Arrays.asList("ab-abc-abcd-abcde-abcdef", "5-2-3-1-4");List<String> newList4 = list4.stream().flatMap(s -> Arrays.stream(s.split("-"))).collect(Collectors.toList());System.out.println("案例4:把一个字符串数组转成另一个字符串数组 " + newList4);System.out.println("-----------------------");//2.4 flatMapToXXX,类似于flatMap,返回一个XXXStream。包括三个方法:flatMapToInt、flatMapToLong、flatMapToDouble//案例5:对给定的二维整数数组求和:int[][] data = {{1, 2}, {3, 4}, {5, 6}};IntStream intStream = Arrays.stream(data).flatMapToInt(row -> Arrays.stream(row));System.out.println("案例5:对给定的二维整数数组求和:" + intStream.sum());System.out.println("-----------------------");//2.5 filter,筛选功能,按照一定的规则将符合条件的元素提取到新的流中。//案例6:找出考试成绩在 90 分以上的学生姓名:List<Student> students = buildStudentList();List<String> nameList = students.stream().filter(x -> x.getScore() >= 90).map(Student::getName).collect(Collectors.toList());System.out.println("案例6:找出考试成绩在90分以上的学生姓名:" + nameList);System.out.println("-----------------------");//2.6 peek,//返回由 stream 中元素组成的新 stream,用给定的函数作用在新 stream 的每个元素上。//传入的函数是一个 Consume 类型的,没有返回值,因此并不会改变原 stream 中元素的值。peek 主要用是 debug,可以方便地 查看流处理结果是否正确。//案例7:过滤出 stream 中长度大于 3 的字符串并转为大写:List<String> collect = Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.print("," + e)).map(String::toUpperCase).peek(e -> System.out.println("->" + e)).collect(Collectors.toList());System.out.println("案例7:过滤出stream中长度大于3的字符串并转为大写:" + collect);System.out.println("-----------------------");//2.7 unordered.//把一个有序的 stream 转成一个无序 stream ,如果原 stream 本身就是无序的,可能会返回原始的 stream。//案例8:把一个有序数组转成无序,每次执行输出的结果不一样。System.out.print("案例8:把一个有序数组转成无序:");Arrays.asList("1", "2", "3", "4", "5").parallelStream().unordered().forEach(r -> System.out.print(r + " "));System.out.println("\n-----------------------");}

2.3 Stream有状态操作

Stream有状态操作:distinct,limit,skip,sorted

/*** 3.Stream有状态操作* 3.1 distinct* 3.2 limit* 3.3 skip* 3.4 sorted*/@Testpublic void operationStreamState() {//3.1 distinct,去重功能。//案例9 :去掉字符串数组中的重复字符串String[] array = {"a", "b", "b", "c", "c", "d", "d", "e", "e"};List<String> newList = Arrays.stream(array).distinct().collect(Collectors.toList());System.out.println("案例9 :去掉字符串数组中的重复字符串:" + newList);System.out.println("-----------------------");//3.2 limit,限制从 stream 中获取前 n 个元素。//案例10 :从数组中获取前 5 个元素String[] array10 = {"c", "c", "a", "b", "b", "e", "e", "d", "d"};List<String> newList10 = Arrays.stream(array10).limit(5).collect(Collectors.toList());System.out.println("案例10 :从数组中获取前 5 个元素:" + newList10);System.out.println("-----------------------");//3.3 skip,跳过 Stream 中前 n 个元素//案例11:从数组中获取第5个元素之后的元素String[] array11 = {"a", "b", "c", "d", "e", "f", "g", "h", "i"};List<String> newList11 = Arrays.stream(array11).skip(5).collect(Collectors.toList());System.out.println("案例11:从数组中获取前5个元素之后的元素:" + newList11);System.out.println("-----------------------");//3.4 sorted,排序功能。//案例12:对给定数组进行排序String[] array12 = {"c", "c", "a", "b", "b", "e", "e", "d", "d"};List<String> newList12 = Arrays.stream(array12).sorted().collect(Collectors.toList());System.out.println("案例12:对给定数组进行排序:" + newList12);Integer[] array121 = {3, 6, 5, 4, 1, 2, 2, 3, 6};List<Integer> newList121 = Arrays.stream(array121).sorted().collect(Collectors.toList());System.out.println("案例12:对给定数组进行排序:" + newList121);System.out.println("-----------------------");//案例13:按照学生成绩进行排序,正序。List<Student> students = buildStudentList();List<String> nameList = students.stream().sorted(Comparator.comparing(Student::getScore)).map(Student::getName).collect(Collectors.toList());System.out.println("案例13:按照学生成绩进行排序:" + nameList);System.out.println("-----------------------");}

2.4 Stream短路操作

Stream短路操作:findAny,anyMatch,allMatch,noneMatch,findFirst

    /*** 4.Stream短路操作* 4.1 findAny* 4.2 anyMatch* 4.3 allMatch* 4.4 noneMatch* 4.5 findFirst*/@Testpublic void operationStreamShortCircuit() {//4.1 findAny,找出 stream 中任何一个满足过滤条件的元素。//案例14:找出任何一个成绩高于 90 分的学生。排完序取得第一个,最高分。List<Student> students = buildStudentList();Optional<Student> studentFindAny = students.stream().filter(x -> x.getScore() > 90).findAny();System.out.println("案例14:找出任意一个考试成绩在90分以上的学生姓名:" + studentFindAny.orElseGet(null).getName());System.out.println("-----------------------");//4.2 anyMatch,是否存在任意一个满足给定条件的元素。//案例15:是否存在成绩高于 90 分的学生,是否存在成绩低于 50 分的学生。boolean result1 = students.stream().anyMatch(x -> x.getScore() > 90);System.out.println("案例15:是否存在成绩高于 90 分的学生:" + result1);boolean result2 = students.stream().anyMatch(x -> x.getScore() < 50);System.out.println("案例15:是否存在成绩低于 50 分的学生:" + result2);System.out.println("-----------------------");//4.3 allMatch,是否集合中所有元素都满足给定的条件,如果集合是空,则返回 true。//案例16:学生成绩是否都高于 90 分,是否都高于 50 分。boolean result16 = students.stream().allMatch(x -> x.getScore() > 90);System.out.println("案例16:是否所有学生的成绩都高于90分:" + result16);boolean result26 = students.stream().allMatch(x -> x.getScore() > 50);System.out.println("案例16:是否所有学生的成绩都高于50分:" + result26);System.out.println("-----------------------");//4.4 noneMatch,是否没有元素能匹配给定的条件,如果集合是空,则返回 true。//案例17:是不是没有学生成绩在 90 分以上,是否没有学生成绩在 50 分以下。boolean result17 = students.stream().noneMatch(x -> x.getScore() > 90);System.out.println("案例17:是不是没有学生成绩在 90 分以上:" + result17);boolean result27 = students.stream().noneMatch(x -> x.getScore() < 50);System.out.println("案例17:是不是没有学生成绩在 50 分以下:" + result27);System.out.println("-----------------------");//4.5 findFirst,找出第一个符合条件的元素。//案例18:找出第一个成绩在 90 分以上的学生。Optional<Student> studentFindFirst = students.stream().filter(x -> x.getScore() > 90).findFirst();System.out.println("案例18:第一个成绩在 90 分以上的学生姓名:" + studentFindFirst.orElseGet(null).getName());System.out.println("-----------------------");}

2.5 Stream非短路操作

Stream非短路操作:forEach,forEachOrdered,toArray,reduce,collect,max、min、count

/*** 5.Stream非短路操作* 5.1 forEach* 5.2 forEachOrdered* 5.3 toArray* 5.4 reduce* 5.5 collect* 5.6 max、min、count*/@Testpublic void operationStreamNonShortCircuit() {//5.1 forEach,遍历元素。//案例19:遍历一个数组并打印List<Integer> array = Arrays.asList(5, 2, 3, 1, 4);System.out.print("案例19:遍历一个数组并打印:");array.stream().forEach(System.out::print);System.out.println("\n-----------------------");//5.2 forEachOrdered,按照给定集合中元素的顺序输出。主要使用场景是在并行流的情况下,按照给定的顺序输出元素。//案例20:用并行流遍历一个数组并按照给定数组的顺序输出结果System.out.print("案例20:用并行流遍历一个数组并按照给定数组的顺序输出结果:");array.parallelStream().forEachOrdered(System.out::print);System.out.println("\n-----------------------");//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();//注意:stream流只能使用一次就好自动关闭,不能转化多次,所以newArray1,newArray2,newArray3不能同时放开//如果要使用多次就要使用复制功能,把stream复制为输入流多次拷贝System.out.println("案例21:把给定字符串流转化成数组:" + Arrays.asList(newArray1));System.out.println("-----------------------");//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("案例22:数组元素之和:" + sum.get());System.out.println("案例22:数组元素乘积:" + product.get());System.out.println("案例22:数组元素最大值:" + max.get());//案例23:求全班学生最高分、全班学生总分List<Student> students = buildStudentList();Optional<Integer> maxScore = students.stream().map(r -> r.getScore()).reduce(Integer::max);Optional<Integer> sumScore = students.stream().map(r -> r.getScore()).reduce(Integer::sum);Optional<Integer> minScore = students.stream().map(r -> r.getScore()).reduce(Integer::min);System.out.println("案例23:全班学生最高分:" + maxScore.get());System.out.println("案例23:全班学生最低分:" + minScore.get());System.out.println("案例23:全班学生总分:" + sumScore.get());System.out.println("-----------------------");//5.5 collect,把 stream 中的元素归集到新的集合或者归集成单个元素。//5.5.1 归集成新集合,方法包括 toList、toSet、toMap。//案例24:根据学生列表,归纳出姓名列表、不同分数列表、姓名分数集合,其中 Mike 和 Jessie 的分数都是 88。List<String> lists = 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("案例24:全班学生姓名列表:" + lists);System.out.println("案例24:全班学生不同分数列表:" + set);System.out.println("案例24:全班学生姓名分数集合:" + map);System.out.println("-----------------------");//5.5.2 统计功能,统计功能包括如下方法://求总和count,求和summingInt,summingLong,summingDouble//求平均值averagingInt,averagingLong,averagingDouble//求最大/最小值maxBy,minBy//综合统计summarizingInt,summarizingLong,summarizingDouble,//案例25:求总数、求和、最大/最小/平均值//List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);long count = list.stream().collect(Collectors.counting());int summingInt = list.stream().collect(Collectors.summingInt(r -> r));double averagingDouble = list.stream().collect(Collectors.averagingDouble(r -> r));Optional<Integer> maxBy = list.stream().collect(Collectors.maxBy(Integer::compare));Optional<Integer> minBy = list.stream().collect(Collectors.minBy(Integer::compare));System.out.println("案例25:总数:" + count);System.out.println("案例25:总和:" + summingInt);System.out.println("案例25:平均值:" + averagingDouble);System.out.println("案例25:最大值:" + maxBy.get());System.out.println("案例25:最小值:" + minBy.get());System.out.println("-----------------------");//5.5.3 分区和分组,主要包括两个函数:partitioningBy:把stream分成两个map,groupingBy:把stream分成多个map//案例27:将学生按照 80 分以上和以下分区Map<Boolean, List<Student>> partitionByScore = students.stream().collect(Collectors.partitioningBy(x -> x.getScore() > 80));System.out.println("案例27:将学生按照考试成绩80分以上分区:" + partitionByScore);partitionByScore.forEach((k, v) -> {System.out.print(k ? "80分以上:" : "80分以下:");v.forEach(r -> System.out.print(r.getName() + ","));System.out.println();});System.out.println("-----------------------");//案例28:将学生按照性别、年龄分组Map<String, Map<Integer, List<Student>>> group = students.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getScore)));System.out.println("案例28:将学生按照性别、年龄分组:");group.forEach((k, v) -> {System.out.println("male".equals(k) ? "小哥哥:" : "小姐姐:");v.forEach((k1, v1) -> {System.out.print("  " + k1 + ":");v1.forEach(r -> System.out.print(r.getName() + ","));System.out.println();});});System.out.println("-----------------------");//5.5.4 连接,将 stream 中的元素用指定的连接符合并,连接符可以是空。//案例29:输出所有学生的姓名,用逗号分隔,这里还是使用案例 27 中的学生列表String studentNames = students.stream().map(r -> r.getName()).collect(Collectors.joining(","));System.out.println("案例29:所有学生姓名列表:" + studentNames);System.out.println("-----------------------");//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, (sums, b) -> sums + b));System.out.println("案例30:数组中每个元素加1后总和:" + listSum);System.out.println("-----------------------");//5.6 max、min、count,stream 提供的方便统计的方法。//案例31:统计整数数组中最大值、最小值、大于3的元素个数//List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);System.out.println("案例31:数组元素最大值:" + list.stream().max(Integer::compareTo).get());System.out.println("案例31:数组元素最小值:" + list.stream().min(Integer::compareTo).get());System.out.println("案例31:数组中大于3的元素个数:" + list.stream().filter(x -> x > 3).count());System.out.println("-----------------------");//案例32:统计分数最高的学生姓名Optional<Student> optional = students.stream().max(Comparator.comparing(r -> r.getScore()));System.out.println("案例32:成绩最高的学生姓名:" + optional.get().getName() + ": " + optional.get().getScore());System.out.println("-----------end------------");}

3. 测试验证

StreamTest 包含以上案例,是个完整的测试案例。

package com.jerry.unit.stream;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;/*** Stream流测试** @author zrj* @since 2022/4/27**/
public class StreamTest {/*** 1.创建Stream* 1.1 使用集合创建* 1.2 使用数组创建* 1.3 使用 Stream 静态方法*/@Testpublic void createStream() {//1.1使用集合创建List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);Stream streamInt = list.stream();printStream(streamInt, "1.1使用集合创建Stream:");System.out.println("-----------------------");//1.2使用数组创建String[] array = {"ab", "abc", "abcd", "abcde", "abcdef"};Stream<String> streamStr = Arrays.stream(array);printStream(streamStr, "1.2使用数组创建Stream:");System.out.println("-----------------------");//1.3使用 Stream 静态方法Stream<String> streamStatic = Stream.of("ab", "abc", "abcd", "abcde", "abcdef");printStream(streamStatic, "1.3使用 Stream 静态方法Stream:");System.out.println("-----------------------");Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 3).limit(5);printStream(stream4, "Stream迭代器:");Stream<Integer> stream5 = Stream.generate(new Random()::nextInt).limit(3);printStream(stream5, "Stream构建器:");System.out.println("-----------------------");}/*** 2.Stream无状态操作* 2.1 map* 2.2 mapToXXX* 2.3 flatMap* 2.4 flatMapToXXX* 2.5 filter* 2.6 peek* 2.7 unordered*/@Testpublic void operationStreamStateless() {//2.1 map,接收一个函数作为入参,把这个函数应用到每个元素上,执行结果组成一个新的 stream 返回。//案例1:对整数数组每个元素加3 :List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);List<Integer> newList = list.stream().map(x -> x + 3).collect(Collectors.toList());System.out.println("案例1:对整数数组每个元素加3的值:" + newList);//案例2:把字符串数组的每个元素转换为大写:List<String> listStr = Arrays.asList("ab", "abc", "abcd", "abcde", "abcdef");List<String> newListStr = listStr.stream().map(String::toUpperCase).collect(Collectors.toList());System.out.println("案例2:把字符串数组的每个元素转换为大写:" + newListStr);System.out.println("-----------------------");//2.2 mapToXXX,包括三个方法:mapToInt、mapToDouble、mapToLong//案例3:把字符串数组转为整数数组:List<String> listStr3 = Arrays.asList("ab", "abc", "abcd", "abcde", "abcdef");int[] newList3 = listStr3.stream().mapToInt(r -> r.length()).toArray();System.out.println("案例3:把字符串数组转为整数数组: " + Arrays.toString(newList3));System.out.println("-----------------------");//2.3 flatMap,flatMap接收函数作为入参,然后把集合中每个元素转换成一个stream,再把这些stream组成一个新的stream,是拆分单词很好的工具。//案例4:把一个字符串数组转成另一个字符串数组:List<String> list4 = Arrays.asList("ab-abc-abcd-abcde-abcdef", "5-2-3-1-4");List<String> newList4 = list4.stream().flatMap(s -> Arrays.stream(s.split("-"))).collect(Collectors.toList());System.out.println("案例4:把一个字符串数组转成另一个字符串数组 " + newList4);System.out.println("-----------------------");//2.4 flatMapToXXX,类似于flatMap,返回一个XXXStream。包括三个方法:flatMapToInt、flatMapToLong、flatMapToDouble//案例5:对给定的二维整数数组求和:int[][] data = {{1, 2}, {3, 4}, {5, 6}};IntStream intStream = Arrays.stream(data).flatMapToInt(row -> Arrays.stream(row));System.out.println("案例5:对给定的二维整数数组求和:" + intStream.sum());System.out.println("-----------------------");//2.5 filter,筛选功能,按照一定的规则将符合条件的元素提取到新的流中。//案例6:找出考试成绩在 90 分以上的学生姓名:List<Student> students = buildStudentList();List<String> nameList = students.stream().filter(x -> x.getScore() >= 90).map(Student::getName).collect(Collectors.toList());System.out.println("案例6:找出考试成绩在90分以上的学生姓名:" + nameList);System.out.println("-----------------------");//2.6 peek,//返回由 stream 中元素组成的新 stream,用给定的函数作用在新 stream 的每个元素上。//传入的函数是一个 Consume 类型的,没有返回值,因此并不会改变原 stream 中元素的值。peek 主要用是 debug,可以方便地 查看流处理结果是否正确。//案例7:过滤出 stream 中长度大于 3 的字符串并转为大写:List<String> collect = Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.print("," + e)).map(String::toUpperCase).peek(e -> System.out.println("->" + e)).collect(Collectors.toList());System.out.println("案例7:过滤出stream中长度大于3的字符串并转为大写:" + collect);System.out.println("-----------------------");//2.7 unordered.//把一个有序的 stream 转成一个无序 stream ,如果原 stream 本身就是无序的,可能会返回原始的 stream。//案例8:把一个有序数组转成无序,每次执行输出的结果不一样。System.out.print("案例8:把一个有序数组转成无序:");Arrays.asList("1", "2", "3", "4", "5").parallelStream().unordered().forEach(r -> System.out.print(r + " "));System.out.println("\n-----------------------");}/*** 3.Stream有状态操作* 3.1 distinct* 3.2 limit* 3.3 skip* 3.4 sorted*/@Testpublic void operationStreamState() {//3.1 distinct,去重功能。//案例9 :去掉字符串数组中的重复字符串String[] array = {"a", "b", "b", "c", "c", "d", "d", "e", "e"};List<String> newList = Arrays.stream(array).distinct().collect(Collectors.toList());System.out.println("案例9 :去掉字符串数组中的重复字符串:" + newList);System.out.println("-----------------------");//3.2 limit,限制从 stream 中获取前 n 个元素。//案例10 :从数组中获取前 5 个元素String[] array10 = {"c", "c", "a", "b", "b", "e", "e", "d", "d"};List<String> newList10 = Arrays.stream(array10).limit(5).collect(Collectors.toList());System.out.println("案例10 :从数组中获取前 5 个元素:" + newList10);System.out.println("-----------------------");//3.3 skip,跳过 Stream 中前 n 个元素//案例11:从数组中获取第5个元素之后的元素String[] array11 = {"a", "b", "c", "d", "e", "f", "g", "h", "i"};List<String> newList11 = Arrays.stream(array11).skip(5).collect(Collectors.toList());System.out.println("案例11:从数组中获取前5个元素之后的元素:" + newList11);System.out.println("-----------------------");//3.4 sorted,排序功能。//案例12:对给定数组进行排序String[] array12 = {"c", "c", "a", "b", "b", "e", "e", "d", "d"};List<String> newList12 = Arrays.stream(array12).sorted().collect(Collectors.toList());System.out.println("案例12:对给定数组进行排序:" + newList12);Integer[] array121 = {3, 6, 5, 4, 1, 2, 2, 3, 6};List<Integer> newList121 = Arrays.stream(array121).sorted().collect(Collectors.toList());System.out.println("案例12:对给定数组进行排序:" + newList121);System.out.println("-----------------------");//案例13:按照学生成绩进行排序,正序。List<Student> students = buildStudentList();List<String> nameList = students.stream().sorted(Comparator.comparing(Student::getScore)).map(Student::getName).collect(Collectors.toList());System.out.println("案例13:按照学生成绩进行排序:" + nameList);System.out.println("-----------------------");}/*** 4.Stream短路操作* 4.1 findAny* 4.2 anyMatch* 4.3 allMatch* 4.4 noneMatch* 4.5 findFirst*/@Testpublic void operationStreamShortCircuit() {//4.1 findAny,找出 stream 中任何一个满足过滤条件的元素。//案例14:找出任何一个成绩高于 90 分的学生。排完序取得第一个,最高分。List<Student> students = buildStudentList();Optional<Student> studentFindAny = students.stream().filter(x -> x.getScore() > 90).findAny();System.out.println("案例14:找出任意一个考试成绩在90分以上的学生姓名:" + studentFindAny.orElseGet(null).getName());System.out.println("-----------------------");//4.2 anyMatch,是否存在任意一个满足给定条件的元素。//案例15:是否存在成绩高于 90 分的学生,是否存在成绩低于 50 分的学生。boolean result1 = students.stream().anyMatch(x -> x.getScore() > 90);System.out.println("案例15:是否存在成绩高于 90 分的学生:" + result1);boolean result2 = students.stream().anyMatch(x -> x.getScore() < 50);System.out.println("案例15:是否存在成绩低于 50 分的学生:" + result2);System.out.println("-----------------------");//4.3 allMatch,是否集合中所有元素都满足给定的条件,如果集合是空,则返回 true。//案例16:学生成绩是否都高于 90 分,是否都高于 50 分。boolean result16 = students.stream().allMatch(x -> x.getScore() > 90);System.out.println("案例16:是否所有学生的成绩都高于90分:" + result16);boolean result26 = students.stream().allMatch(x -> x.getScore() > 50);System.out.println("案例16:是否所有学生的成绩都高于50分:" + result26);System.out.println("-----------------------");//4.4 noneMatch,是否没有元素能匹配给定的条件,如果集合是空,则返回 true。//案例17:是不是没有学生成绩在 90 分以上,是否没有学生成绩在 50 分以下。boolean result17 = students.stream().noneMatch(x -> x.getScore() > 90);System.out.println("案例17:是不是没有学生成绩在 90 分以上:" + result17);boolean result27 = students.stream().noneMatch(x -> x.getScore() < 50);System.out.println("案例17:是不是没有学生成绩在 50 分以下:" + result27);System.out.println("-----------------------");//4.5 findFirst,找出第一个符合条件的元素。//案例18:找出第一个成绩在 90 分以上的学生。Optional<Student> studentFindFirst = students.stream().filter(x -> x.getScore() > 90).findFirst();System.out.println("案例18:第一个成绩在 90 分以上的学生姓名:" + studentFindFirst.orElseGet(null).getName());System.out.println("-----------------------");}/*** 5.Stream非短路操作* 5.1 forEach* 5.2 forEachOrdered* 5.3 toArray* 5.4 reduce* 5.5 collect* 5.6 max、min、count*/@Testpublic void operationStreamNonShortCircuit() {//5.1 forEach,遍历元素。//案例19:遍历一个数组并打印List<Integer> array = Arrays.asList(5, 2, 3, 1, 4);System.out.print("案例19:遍历一个数组并打印:");array.stream().forEach(System.out::print);System.out.println("\n-----------------------");//5.2 forEachOrdered,按照给定集合中元素的顺序输出。主要使用场景是在并行流的情况下,按照给定的顺序输出元素。//案例20:用并行流遍历一个数组并按照给定数组的顺序输出结果System.out.print("案例20:用并行流遍历一个数组并按照给定数组的顺序输出结果:");array.parallelStream().forEachOrdered(System.out::print);System.out.println("\n-----------------------");//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();//注意:stream流只能使用一次就好自动关闭,不能转化多次,所以newArray1,newArray2,newArray3不能同时放开//如果要使用多次就要使用复制功能,把stream复制为输入流多次拷贝System.out.println("案例21:把给定字符串流转化成数组:" + Arrays.asList(newArray1));System.out.println("-----------------------");//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("案例22:数组元素之和:" + sum.get());System.out.println("案例22:数组元素乘积:" + product.get());System.out.println("案例22:数组元素最大值:" + max.get());//案例23:求全班学生最高分、全班学生总分List<Student> students = buildStudentList();Optional<Integer> maxScore = students.stream().map(r -> r.getScore()).reduce(Integer::max);Optional<Integer> sumScore = students.stream().map(r -> r.getScore()).reduce(Integer::sum);Optional<Integer> minScore = students.stream().map(r -> r.getScore()).reduce(Integer::min);System.out.println("案例23:全班学生最高分:" + maxScore.get());System.out.println("案例23:全班学生最低分:" + minScore.get());System.out.println("案例23:全班学生总分:" + sumScore.get());System.out.println("-----------------------");//5.5 collect,把 stream 中的元素归集到新的集合或者归集成单个元素。//5.5.1 归集成新集合,方法包括 toList、toSet、toMap。//案例24:根据学生列表,归纳出姓名列表、不同分数列表、姓名分数集合,其中 Mike 和 Jessie 的分数都是 88。List<String> lists = 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("案例24:全班学生姓名列表:" + lists);System.out.println("案例24:全班学生不同分数列表:" + set);System.out.println("案例24:全班学生姓名分数集合:" + map);System.out.println("-----------------------");//5.5.2 统计功能,统计功能包括如下方法://求总和count,求和summingInt,summingLong,summingDouble//求平均值averagingInt,averagingLong,averagingDouble//求最大/最小值maxBy,minBy//综合统计summarizingInt,summarizingLong,summarizingDouble,//案例25:求总数、求和、最大/最小/平均值//List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);long count = list.stream().collect(Collectors.counting());int summingInt = list.stream().collect(Collectors.summingInt(r -> r));double averagingDouble = list.stream().collect(Collectors.averagingDouble(r -> r));Optional<Integer> maxBy = list.stream().collect(Collectors.maxBy(Integer::compare));Optional<Integer> minBy = list.stream().collect(Collectors.minBy(Integer::compare));System.out.println("案例25:总数:" + count);System.out.println("案例25:总和:" + summingInt);System.out.println("案例25:平均值:" + averagingDouble);System.out.println("案例25:最大值:" + maxBy.get());System.out.println("案例25:最小值:" + minBy.get());System.out.println("-----------------------");//5.5.3 分区和分组,主要包括两个函数:partitioningBy:把stream分成两个map,groupingBy:把stream分成多个map//案例27:将学生按照 80 分以上和以下分区Map<Boolean, List<Student>> partitionByScore = students.stream().collect(Collectors.partitioningBy(x -> x.getScore() > 80));System.out.println("案例27:将学生按照考试成绩80分以上分区:" + partitionByScore);partitionByScore.forEach((k, v) -> {System.out.print(k ? "80分以上:" : "80分以下:");v.forEach(r -> System.out.print(r.getName() + ","));System.out.println();});System.out.println("-----------------------");//案例28:将学生按照性别、年龄分组Map<String, Map<Integer, List<Student>>> group = students.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getScore)));System.out.println("案例28:将学生按照性别、年龄分组:");group.forEach((k, v) -> {System.out.println("male".equals(k) ? "小哥哥:" : "小姐姐:");v.forEach((k1, v1) -> {System.out.print("  " + k1 + ":");v1.forEach(r -> System.out.print(r.getName() + ","));System.out.println();});});System.out.println("-----------------------");//5.5.4 连接,将 stream 中的元素用指定的连接符合并,连接符可以是空。//案例29:输出所有学生的姓名,用逗号分隔,这里还是使用案例 27 中的学生列表String studentNames = students.stream().map(r -> r.getName()).collect(Collectors.joining(","));System.out.println("案例29:所有学生姓名列表:" + studentNames);System.out.println("-----------------------");//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, (sums, b) -> sums + b));System.out.println("案例30:数组中每个元素加1后总和:" + listSum);System.out.println("-----------------------");//5.6 max、min、count,stream 提供的方便统计的方法。//案例31:统计整数数组中最大值、最小值、大于3的元素个数//List<Integer> list = Arrays.asList(5, 2, 3, 1, 4);System.out.println("案例31:数组元素最大值:" + list.stream().max(Integer::compareTo).get());System.out.println("案例31:数组元素最小值:" + list.stream().min(Integer::compareTo).get());System.out.println("案例31:数组中大于3的元素个数:" + list.stream().filter(x -> x > 3).count());System.out.println("-----------------------");//案例32:统计分数最高的学生姓名Optional<Student> optional = students.stream().max(Comparator.comparing(r -> r.getScore()));System.out.println("案例32:成绩最高的学生姓名:" + optional.get().getName() + ": " + optional.get().getScore());System.out.println("-----------end------------");}/*** 构建学生集合*/private List<Student> buildStudentList() {List<Student> students = new ArrayList<>();students.add(new Student("Mike", 10, "male", 88));students.add(new Student("Jerry", 18, "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));return students;}/*** 打印Stream** @param stream Stream流* @param msg    输出信息* @return void*/private void printStream(Stream stream, String msg) {System.out.print(msg);stream.forEach(i -> System.out.print(i + ","));System.out.println();}}@Data
@NoArgsConstructor
@AllArgsConstructor
class Student {//定义一个学生类,包含姓名、年龄、性别、考试成绩四个属性private String name;private Integer age;private String sex;private Integer score;
}

Java stream流式计算详解相关推荐

  1. flink大数据处理流式计算详解

    flink大数据处理 文章目录 flink大数据处理 二.WebUI可视化界面(测试用) 三.Flink部署 3.1 JobManager 3.2 TaskManager 3.3 并行度的调整配置 3 ...

  2. JavaSE-常用类、Stream 流式计算

    JavaSE-常用类.Stream 流式计算 常用类 内置包装类 Integer String 类型转换 StringBuilder(JDK1.5) StringBuffer(JDK1.0) Date ...

  3. java8/Stream流式计算从入门到精通/函数式编程实战

    摘要:Stream流式计算,本文讲解了Stream流式计算的概念,具体的使用步骤以及源码实现,最后讲解了使用Stream过程中需要注意的事项.Stream在公司项目中被频繁使用,在性能优化上具有广泛的 ...

  4. Stream流式计算

    一.什么是Stream流式计算(学习此之前,要先知道四大函数式接口) 1.常用的集合是为了存储数集,而对于集合数据的一些处理(像筛选集合数据等)可以使用Stream流来处理         2.jav ...

  5. mysql流式计算,Stream流式计算

    Stream流式计算 什么是Stream流式计算 数据处理中不可缺少的两部分:存储 + 计算 集合.MySQL本质就是存储数据的,计算都应该交给流来操作! package com.kuang.stre ...

  6. Java-Stream流式编程详解

    目录 一.概述 1.1.特性: 不存储数据.不改变数据源.不可重复使用 1.2.生成流的方式 1.3.反转流到集合 二.中间节点与终值节点 2.1.中间节点 2.2.终值节点 三.Stream的方法 ...

  7. Java Stream流式编程

    流式编程Stream 一.简介 流式 API 从 Java8 开始引入,支持链式书写. 流只能消费一次,不能被两次消费(两次最终操作) 流在管道中流通,在节点被处理. 流[无存储],流不是一种数据结构 ...

  8. [编程] Java8 Stream(流式计算) 常见的一些用法汇总

    前提:以下基于 List<Student> 列表进行举例,大家实际使用进行举一反三即可.大同小异,Java8 的流式计算功能很强大,需要大家实际应用中逐渐挖掘更高级的用法. Student ...

  9. java IO流基础 万字详解(从拷贝文件到模拟上传头像)

    目录 一.前言: 二.IO流简介: 1.什么是IO流? 2.IO流能干什么? 3.IO流的分类: 4.IO流体系: 三.字符流读写文件: 1.普通字符流读取文件: 前言: ①以单个字符读取: 代码演示 ...

最新文章

  1. 面向dba的linux shell 脚本简介,面向dba的linuxshell脚本简介.doc
  2. Apache Software Foundation Distribution Directory
  3. python创建脚本文件_python创建文件备份的脚本
  4. bbs php redis,LAMP+redis搭建discuz论坛
  5. 用SecureCRT实现真机跟虚拟机的文件传输
  6. [NewLife.XCode]高级查询(化繁为简、分页提升性能)
  7. mysql主从复制 火墙_MySQL高级知识(十五)——主从复制
  8. 卸载sqlserver
  9. 使用CSS在文字前面加上图标。
  10. c++ 字符串替换指定字符
  11. 负数除以正数余数如何求_负数除正数的余数是正还是负?-工业支持中心-西门子中国...
  12. Ubuntu 18.04 安装 php7.4 --enable-maintainer-zts
  13. mysql strtolower_自己写的mysql类_PHP教程 - strtolower
  14. SISD、MIMD、SIMD、MISD系统介绍
  15. 微信公众平台、微信公众平台.小程序、微信.开放平台三者关系及unionid
  16. 区块链1——区块链基础
  17. python报错:patsy.PatsyError: error tokenizing input (maybe an unclosed string?)
  18. win10字体模糊怎么调节
  19. 阿里云网站备案注销新规则
  20. win10配置android环境变量,adb环境变量配置win10,adb添加环境变量

热门文章

  1. DALAL创建的行人检测INRIA数据库
  2. Python、R和SAS的比较
  3. 专线或祼光纤如何接入到网络中
  4. ifconfig 命令
  5. 欧几里得+扩展欧几里得+RSA
  6. 分位数回归的r语言代码
  7. QCon北京2015精彩内容前瞻:邀请100余位一线专家,涵盖大数据、云计算、移动等20余个专题...
  8. aria2 让下载提速
  9. 学会扒源码-HashMap
  10. 定位云原生数据中台,「智领云」获数千万元A轮融资