Stream流 collect() 方法的使用介绍
1 2 3 4 5 6 <R> R collect (Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) ;<R, A> R collect (Collector<? super T, A, R> collector) ;
Stream 流的注意事项:Stream不调用终止方法,中间的操作不会执行 。
但是,当我们对 Stream 流中的数据操作完成之后,如果需要将流的结果进行保存,方便我们接下来对结果的继续操作,该怎么办呢?
Stream 流提供了一个 **collect() 方法,**可以收集流中的数据到【集合 】或者【数组 】中去。
1.收集 Stream 流中的数据到集合中
1 2 3 4 5 6 7 stream.collect(Collectors.toList()) stream.collect(Collectors.toSet()) Collectors.toCollection(Supplier<C> collectionFactory) stream.collect(Collectors.joining())
示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class CollectDataToCollection { public static void main (String[] args) { Stream<String> stream = Stream.of("aaa" , "bbb" , "ccc" , "bbb" ); List<String> list = stream.collect(Collectors.toList()); System.out.println(list); Set<String> collect = stream.collect(Collectors.toSet()); System.out.println(collect); ArrayList<String> arrayList = stream.collect(Collectors.toCollection(ArrayList::new )); System.out.println(arrayList); HashSet<String> hashSet = stream.collect(Collectors.toCollection(HashSet::new )); System.out.println(hashSet); } }
测试结果:
1 2 3 4 [aaa, bbb, ccc, bbb] [aaa, ccc, bbb] [aaa, bbb, ccc, bbb] [aaa, ccc, bbb]
2.收集 Stream 流中的数据到数组中
1 2 3 4 Object[] toArray(); <A> A[] toArray(IntFunction<A[]> generator);
示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public class CollectDataToArray { public static void main (String[] args) { Stream<String> stream = Stream.of("aaa" , "bbb" , "ccc" , "bbb" ); Object[] objects = stream.toArray(); for (Object o: objects) { System.out.println("data:" +o); } String[] strings = stream.toArray(String[]::new ); for (String str : strings){ System.out.println("data:" +str + ",length:" +str.length()); } } }
测试结果:
1 2 3 4 5 6 7 8 9 data:aaa data:bbb data:ccc data:bbb ----------------- data:aaa,length:3 data:bbb,length:3 data:ccc,length:3 data:bbb,length:3
3.Stream流中数据聚合/分组/分区/拼接操作
除了 collect() 方法将数据收集到集合/数组中。对 Stream流 的收集还有其他的方法。比如说:聚合计算,分组,多级分组,分区,拼接等。
附:Student实体类(接下来介绍,将根据Student类来进行聚合、分组、分区、拼接介绍)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 public class Student { private String name; private int age; private int score; public Student (String name, int age, int score) { this .name = name; this .age = age; this .score = score; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } public int getScore () { return score; } public void setScore (int score) { this .score = score; } @Override public String toString () { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", score=" + score + '}' ; } }
1.聚合操作
当我们使用 Stream 流处理数据后,可以像数据库的聚合函数一样对某个字段进行操作。比如获取最大值,获取最小值,求总和,求平均值,统计数量等操作。
1 2 3 4 5 6 7 8 9 10 Collectors.maxBy(); Collectors.minBy(); Collectors.summingInt();/Collectors.summingDouble();/Collectors.summingLong(); Collectors.averagingInt();/Collectors.averagingDouble();/Collectors.averagingLong(); Collectors.counting();
示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 public class CollectDataToArray { public static void main (String[] args) { Stream<Student> studentStream = Stream.of( new Student ("赵丽颖" , 58 , 95 ), new Student ("杨颖" , 56 , 88 ), new Student ("迪丽热巴" , 56 , 99 ), new Student ("柳岩" , 52 , 77 ) ); Optional<Student> max = studentStream.collect(Collectors.maxBy((s1, s2) -> s1.getScore() - s2.getScore())); System.out.println("最大值:" +max.get()); Optional<Student> min = studentStream.collect(Collectors.minBy((s1, s2) -> s1.getScore() - s2.getScore())); System.out.println("最小值:" +min.get()); Integer ageSum = studentStream.collect(Collectors.summingInt(Student::getAge)); System.out.println("年龄总和:" +ageSum); Double avgScore = studentStream.collect(Collectors.averagingInt(Student::getScore)); System.out.println("分数平均值:" +avgScore); Long count = studentStream.collect(Collectors.counting()); System.out.println("数量为:" +count); } }
测试结果:
1 2 3 4 5 最大值:Student{name='迪丽热巴' , age=56 , score=99 } 最小值:Student{name='柳岩' , age=52 , score=77 } 年龄总和:222 分数平均值:89.75 数量为:4
2.分组操作
当我们使用 Stream 流处理数据后,可以根据某个属性来将数据进行分组。
1 2 groupingBy(Function<? super T, ? extends K > classifier)
示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 public class CollectDataToArray { public static void main (String[] args) { Stream<Student> studentStream = Stream.of( new Student ("赵丽颖" , 52 , 56 ), new Student ("杨颖" , 56 , 88 ), new Student ("迪丽热巴" , 56 , 99 ), new Student ("柳岩" , 52 , 53 ) ); Map<Integer, List<Student>> map = studentStream.collect(Collectors.groupingBy((s -> s.getAge()))); map.forEach((key,value)->{ System.out.println(key + "---->" +value); }); Map<String, List<Student>> map = studentStream.collect(Collectors.groupingBy(s -> { if (s.getScore() >= 60 ) { return "及格" ; } else { return "不及格" ; } })); map.forEach((key,value)->{ System.out.println(key + "---->" +value.get()); }); Map<Integer, Optional<Student>> reducingMap = studentStream.collect( Collectors.groupingBy(Student::getAge, Collectors.reducing( BinaryOperator.maxBy( Comparator.comparingInt(Student::getScore) ) ) ) ); reducingMap .forEach((key,value)->{ System.out.println(key + "---->" +value); }); } }
测试结果:
1 2 3 4 5 6 7 8 52 ---->[Student{name='赵丽颖' , age=52 , score=56 }, Student{name='柳岩' , age=52 , score=53 }]56 ---->[Student{name='杨颖' , age=56 , score=88 }, Student{name='迪丽热巴' , age=56 , score=99 }]----------------------------------------------------------------------------------------------- 不及格---->[Student{name='赵丽颖' , age=52 , score=56 }, Student{name='柳岩' , age=52 , score=53 }] 及格---->[Student{name='杨颖' , age=56 , score=88 }, Student{name='迪丽热巴' , age=56 , score=99 }] ----------------------------------------------------------------------------------------------- 52 ---->Student{name='赵丽颖' , age=52 , score=95 }56 ---->Student{name='杨颖' , age=56 , score=88 }
3.多级分组操作
当我们使用 Stream 流处理数据后,可以根据某个属性来将数据进行分组。
1 2 groupingBy(Function<? super T, ? extends K > classifier,Collector<? super T, A, D> downstream)
示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 public class CollectDataToArray { public static void main (String[] args) { Stream<Student> studentStream = Stream.of( new Student ("赵丽颖" , 52 , 95 ), new Student ("杨颖" , 56 , 88 ), new Student ("迪丽热巴" , 56 , 55 ), new Student ("柳岩" , 52 , 33 ) ); Map<Integer, Map<Integer, Map<String, List<Student>>>> map = studentStream.collect(Collectors.groupingBy(str -> str.getAge(), Collectors.groupingBy(str -> str.getScore(), Collectors.groupingBy((student) -> { if (student.getScore() >= 60 ) { return "及格" ; } else { return "不及格" ; } })))); map.forEach((key,value)->{ System.out.println("年龄:" + key); value.forEach((k2,v2)->{ System.out.println("\t" + v2); }); }); } }
测试结果:
1 2 3 4 5 6 年龄:52 {不及格=[Student{name='柳岩' , age=52 , score=33 }]} {及格=[Student{name='赵丽颖' , age=52 , score=95 }]} 年龄:56 {不及格=[Student{name='迪丽热巴' , age=56 , score=55 }]} {及格=[Student{name='杨颖' , age=56 , score=88 }]}
4.分区操作
我们在前面学习了 Stream流中数据的分组操作,我们可以根据属性完成对数据的分组。接下来我们介绍分区操作,我们通过使用 Collectors.partitioningBy() ,根据返回值是否为 true,把集合分为两个列表,一个 true 列表,一个 false 列表。
**分组和分区的区别就在:**分组可以有多个组。分区只会有两个区( true 和 false)
1 2 3 4 5 partitioningBy(Predicate<? super T> predicate) partitioningBy(Predicate<? super T> predicate, Collector<? super T, A, D> downstream)
示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class CollectDataToArray { public static void main (String[] args) { Stream<Student> studentStream = Stream.of( new Student ("赵丽颖" , 52 , 95 ), new Student ("杨颖" , 56 , 88 ), new Student ("迪丽热巴" , 56 , 55 ), new Student ("柳岩" , 52 , 33 ) ); Map<Boolean, List<Student>> partitionMap = studentStream.collect(Collectors.partitioningBy(s -> s.getScore() > 60 )); partitionMap.forEach((key,value)->{ System.out.println(key + "---->" + value); }); } }
测试结果:
1 2 false ---->[Student{name='迪丽热巴' , age=56 , score=55 }, Student{name='柳岩' , age=52 , score=33 }]true ---->[Student{name='赵丽颖' , age=52 , score=95 }, Student{name='杨颖' , age=56 , score=88 }]
5.拼接操作
**Collectors.joining() **会根据指定的连接符,将所有元素连接成一个字符串。
1 2 3 4 5 6 joining() joining(CharSequence delimiter) joining(CharSequence delimiter, CharSequence prefix,CharSequence suffix)
示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class CollectDataToArray { public static void main (String[] args) { Stream<Student> studentStream = Stream.of( new Student ("赵丽颖" , 52 , 95 ), new Student ("杨颖" , 56 , 88 ), new Student ("迪丽热巴" , 56 , 55 ), new Student ("柳岩" , 52 , 33 ) ); String joinStr1 = studentStream.map(s -> s.getName()).collect(Collectors.joining()); System.out.println(joinStr1); String joinStr2 = studentStream.map(s -> s.getName()).collect(Collectors.joining("," )); System.out.println(joinStr2); String joinStr3 = studentStream.map(s -> s.getName()).collect(Collectors.joining("—" ,"^_^" ,">_<" )); System.out.println(joinStr3); } }
测试结果:
1 2 3 赵丽颖杨颖迪丽热巴柳岩 赵丽颖,杨颖,迪丽热巴,柳岩 ^_^赵丽颖—杨颖—迪丽热巴—柳岩>_<