Stream流 collect() 方法的使用介绍

//1.
<R> R collect(Supplier<R> supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);
//2.
<R, A> R collect(Collector<? super T, A, R> collector);

Stream 流的注意事项:Stream不调用终止方法,中间的操作不会执行。

但是,当我们对 Stream 流中的数据操作完成之后,如果需要将流的结果进行保存,方便我们接下来对结果的继续操作,该怎么办呢?

Stream 流提供了一个 collect() 方法,可以收集流中的数据到【集合】或者【数组】中去。

1.收集 Stream 流中的数据到集合中

//1.收集数据到list集合中
stream.collect(Collectors.toList())
//2.收集数据到set集合中
stream.collect(Collectors.toSet())
//3.收集数据到指定的集合中
Collectors.toCollection(Supplier<C> collectionFactory)
stream.collect(Collectors.joining())

示例如下:

/*** 收集Stream流中的数据到集合中* 备注:切记Stream流只能被消费一次,流就失效了* 如下只是示例代码*/
public class CollectDataToCollection{public static void main(String[] args) {//Stream 流Stream<String> stream = Stream.of("aaa", "bbb", "ccc", "bbb");//收集流中的数据到集合中//1.收集流中的数据到 listList<String> list = stream.collect(Collectors.toList());System.out.println(list);//2.收集流中的数据到 setSet<String> collect = stream.collect(Collectors.toSet());System.out.println(collect);//3.收集流中的数据(ArrayList)(不收集到list,set等集合中,而是)收集到指定的集合中ArrayList<String> arrayList = stream.collect(Collectors.toCollection(ArrayList::new));System.out.println(arrayList);//4.收集流中的数据到 HashSetHashSet<String> hashSet = stream.collect(Collectors.toCollection(HashSet::new));System.out.println(hashSet);}
}

测试结果:

[aaa, bbb, ccc, bbb]
[aaa, ccc, bbb]
[aaa, bbb, ccc, bbb]
[aaa, ccc, bbb]

2.收集 Stream 流中的数据到数组中

//1.使用无参,收集到数组,返回值为 Object[](Object类型将不好操作)
Object[] toArray();
//2.使用有参,可以指定将数据收集到指定类型数组,方便后续对数组的操作
<A> A[] toArray(IntFunction<A[]> generator);

示例如下:

/*** 收集Stream流中的数据到数组中* 备注:切记Stream流只能被消费一次,流就失效了* 如下只是示例代码*/
public class CollectDataToArray{public static void main(String[] args) {//Stream 流Stream<String> stream = Stream.of("aaa", "bbb", "ccc", "bbb");//2.1 使用 toArray()无参Object[] objects = stream.toArray();for (Object o: objects) {//此处无法使用.length() 等方法System.out.println("data:"+o);}//2.2 使用有参返回指定类型数组//无参不好的一点就是返回的是 Object[] 类型,操作比较麻烦.想要拿到长度,Object是拿不到长度的String[] strings = stream.toArray(String[]::new);for(String str : strings){System.out.println("data:"+str + ",length:"+str.length());}}
}

测试结果:

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类来进行聚合、分组、分区、拼接介绍)

/*** TODO Student实体类** @author liuzebiao*/
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;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}
}

1.聚合操作

当我们使用 Stream 流处理数据后,可以像数据库的聚合函数一样对某个字段进行操作。比如获取最大值,获取最小值,求总和,求平均值,统计数量等操作。

//最大值
Collectors.maxBy();
//最小值
Collectors.minBy();
//总和
Collectors.summingInt();/Collectors.summingDouble();/Collectors.summingLong();
//平均值
Collectors.averagingInt();/Collectors.averagingDouble();/Collectors.averagingLong();
//总个数
Collectors.counting();

示例如下:

/*** Stream流数据--聚合操作* 备注:切记Stream流只能被消费一次,流就失效了* 如下只是示例代码* @author liuzebiao*/
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));//聚合操作//获取最大值(Stream流 max()方法亦可)//max()方法实现//Optional<Student> max = studentStream.max((s1, s2) -> s1.getScore() - s2.getScore());//(聚合)实现Optional<Student> max = studentStream.collect(Collectors.maxBy((s1, s2) -> s1.getScore() - s2.getScore()));System.out.println("最大值:"+max.get());//获取最小值(Stream流 min()方法亦可)//min()方法实现//Optional<Student> min = studentStream.max((s1, s2) -> s2.getScore() - s1.getScore());//(聚合)实现Optional<Student> min = studentStream.collect(Collectors.minBy((s1, s2) -> s1.getScore() - s2.getScore()));System.out.println("最小值:"+min.get());//求总和(使用Stream流的map()和reduce()方法亦可求和)//map()和reduce()方法实现//Integer reduce = studentStream.map(s -> s.getAge()).reduce(0, Integer::sum);//(聚合)简化前//Integer ageSum = studentStream.collect(Collectors.summingInt(s->s.getAge()));//(聚合)使用方法引用简化Integer ageSum = studentStream.collect(Collectors.summingInt(Student::getAge));System.out.println("年龄总和:"+ageSum);//求平均值//(聚合)简化前//Double avgScore = studentStream.collect(Collectors.averagingInt(s->s.getScore()));//(聚合)使用方法引用简化Double avgScore = studentStream.collect(Collectors.averagingInt(Student::getScore));System.out.println("分数平均值:"+avgScore);//统计数量(Stream流 count()方法亦可)//count()方法实现//long count = studentStream.count();//(聚合)统计数量Long count = studentStream.collect(Collectors.counting());System.out.println("数量为:"+count);}
}

测试结果:

最大值:Student{name='迪丽热巴', age=56, score=99}
最小值:Student{name='柳岩', age=52, score=77}
年龄总和:222
分数平均值:89.75
数量为:4

2.分组操作

当我们使用 Stream 流处理数据后,可以根据某个属性来将数据进行分组。

//接收一个 Function 参数
groupingBy(Function<? super T, ? extends K> classifier)

示例如下:

/*** Stream流数据--分组操作* 备注:切记Stream流只能被消费一次,流就失效了* 如下只是示例代码* @author liuzebiao*/
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));//1.按照具体年龄分组Map<Integer, List<Student>> map = studentStream.collect(Collectors.groupingBy((s -> s.getAge())));map.forEach((key,value)->{System.out.println(key + "---->"+value);});//2.按照分数>=60 分为"及格"一组  <60 分为"不及格"一组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());});//3.按照年龄分组,规约求每组的最大值最小值(规约:reducing)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);});}
}

测试结果:

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.Function 参数  2.Collector多级分组
groupingBy(Function<? super T, ? extends K> classifier,Collector<? super T, A, D> downstream)

示例如下:

/*** Stream流数据--多级分组操作* 备注:切记Stream流只能被消费一次,流就失效了* 如下只是示例代码* @author liuzebiao* @Date 2020-1-10 13: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));//多级分组//1.先根据年龄分组,然后再根据成绩分组//分析:第一个Collectors.groupingBy() 使用的是(年龄+成绩)两个维度分组,所以使用两个参数 groupingBy()方法//    第二个Collectors.groupingBy() 就是用成绩分组,使用一个参数 groupingBy() 方法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);});});}
}

测试结果:

年龄: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.一个参数
partitioningBy(Predicate<? super T> predicate)//2.两个参数(多级分区)
partitioningBy(Predicate<? super T> predicate, Collector<? super T, A, D> downstream)

示例如下:

/*** Stream流数据--多级分组操作* 备注:切记Stream流只能被消费一次,流就失效了* 如下只是示例代码* @author liuzebiao*/
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);});}
}

测试结果:

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() 会根据指定的连接符,将所有元素连接成一个字符串。

//无参数--等价于 joining("");
joining()
//一个参数
joining(CharSequence delimiter)
//三个参数(前缀+后缀)
joining(CharSequence delimiter, CharSequence prefix,CharSequence suffix)

示例如下:

/*** Stream流数据--多级分组操作* 备注:切记Stream流只能被消费一次,流就失效了* 如下只是示例代码* @author liuzebiao*/
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));//拼接操作//无参:join()String joinStr1 = studentStream.map(s -> s.getName()).collect(Collectors.joining());System.out.println(joinStr1);//一个参数:joining(CharSequence delimiter)String joinStr2 = studentStream.map(s -> s.getName()).collect(Collectors.joining(","));System.out.println(joinStr2);//三个参数:joining(CharSequence delimiter, CharSequence prefix,CharSequence suffix)String joinStr3 = studentStream.map(s -> s.getName()).collect(Collectors.joining("—","^_^",">_<"));System.out.println(joinStr3);}
}

测试结果:

赵丽颖杨颖迪丽热巴柳岩
赵丽颖,杨颖,迪丽热巴,柳岩
^_^赵丽颖—杨颖—迪丽热巴—柳岩>_<

Java8 Stream流中的 collect() 方法,远比你想象中的强大相关推荐

  1. Java8——Stream流

    Java8--Stream流 Stream是数据渠道,用于操作集合.数组等生成的元素序列. Stream操作的三个步骤: 创建Stream 中间操作 终止操作 一.获取stream的四种方式 1.通过 ...

  2. Java8 Stream 流的创建、筛选、映射、排序、归约、分组、聚合、提取与组合、收集、接合、foreach遍历

    目录 一  了解Stream 1 Stream概述 那么什么是Stream? Stream可以由数组或集合创建 Stream有几个特性: Stream流的起始操作 2 Stream的创建----Str ...

  3. 学习Java8 Stream流,让我们更加便捷的操纵集合

    1. 概述 本篇文章会简略的介绍一下 Lambda 表达式,然后开启我们的正题 Java8 Stream 流,希望观众老爷们多多支持,并在评论区批评指正! Java8 的 Stream 流使用的是函数 ...

  4. java8 Stream流【华为3面】

    华为三面@java8 stream流操作面试题 前言:华为三面考了个很简单的基础编程,就是java8 Stream流操作,太久没写,也是没掌握好java基础直接搞得措手不及,stream两行代码的事情 ...

  5. Stream流的基本使用方法

    Stream流的基本使用方法 0.常用方法 在介绍的各种方法中,凡是返回值仍然为Stream接口的为函数拼接方法,它们支持链式调用:而返回值不再为Stream接口的为终结方法,不再支持链式调用.如下表 ...

  6. Java8 Stream 流 一些使用整理(持续更新)

    Java8 Stream 流 一些使用整理 双循环判断值 原始写法 Stream 普通写法 Stream filter + anyMatch写法 持续更新中 双循环判断值 原始写法 List<C ...

  7. java8 stream流 将一个list转换成list

    java8 stream流 将一个对象集合转换成另一个对象集合 案例一: // 利用stream进行类型转化     List<String> stringList = new Array ...

  8. lambda stream流处理异常的方法/Either不终止stream流处理异常

    lambda stream流处理异常的方法/Either不终止stream流处理异常 1.直接用try/catch捕获 1.1 stream流中使用try/catch 案例如下,在list中存在可能引 ...

  9. 大洗牌中的中国服务业:这个冬天远比你想象中寒冷

    大洗牌中的中国服务业:这个冬天远比你想象中寒冷 没有想到,去年爆火的一句"我太难了", 不是对2019年的总结,而是对魔幻2020年的一个预言. 短短两个月,我们就经历了美伊纷争. ...

最新文章

  1. java B2B2C 源码 多级分销Springcloud多租户电子商城系统- 整合企业架构的技术点(二)...
  2. 寻找人机之间的中间地带-评述3本人机协作的书
  3. Xcode文件被锁定:The file .xcodeproj could not be unlocked
  4. Highcharts-2.3.2 网页曲线绘制工具 一淘网价格曲线
  5. 带有Java和Axis2的JSON Web服务
  6. I/O模型系列之四:两种高性能IO设计模式 Reactor 和 Proactor
  7. Spring精华问答 | 什么是YAML?
  8. 曾遭闪电贷攻击的Origin将重新推出稳定币OUSD
  9. RHCSA学习笔记-基础操作命令
  10. python中str类型_python的str是什么类型
  11. C# 性能优化之斤斤计较篇 二
  12. 电子科技大学《图论及其应用》复习(史上最全汇总)
  13. fw325r没有虚拟服务器,迅捷fw325r路由器设置完没有网怎么办?
  14. 国标SVAC对飙通行标准,优势何在?
  15. PHP毕业设计——艺术品展示网站
  16. 求助FC上的一个c++代码实现丧心病狂的走迷宫小游戏!
  17. 【LeetCode-SQL】580. 统计各专业学生人数
  18. 0基础学编程需要哪些基础?
  19. 【进阶】34、docker部署mall商城
  20. MyEclipse/eclipse的php开发调试环境配置

热门文章

  1. 如何保护您的网站免受恶意软件的侵害
  2. Elasticsearch生产实战(ik分词器、拼音分词、自动补全、自动纠错)
  3. 2020-12-3 QQ通讯录(不完整内容)
  4. 弘辽科技:打造爆款的三大核心。
  5. Access.2007数据库开发全书(奋斗的小鸟)_PDF 电子书
  6. Excel 宏录制与VBA编程 —— 3、第一个VBA弹窗代码(附视频)
  7. 读论文(二):HMB-SSD: Framework for Efficient Exploiting of the Host Memory Buffer in the NVMe SSD
  8. 还原数据库提示 Unknown collation ‘utf8_general_mysql500_ci’解决方式
  9. RuntimeError: CUDA error: an illegal memory access was encountered的解决方法
  10. c语言实例 魔术师的猜牌术(1),C语言实例 魔术师的猜牌术(1)