【Java 基础】Collectors 使用小结

Collectors 与集合转换
Collectors toList
streamArr.collect(Collectors.toList());
List<Integer> collectList = Stream.of(1, 2, 3, 4)
.collect(Collectors.toList());
System.out.println("collectList: " + collectList);
// 打印结果 collectList: [1, 2, 3, 4]
Collectors toMap
map value 为对象 student
Map<Integer, Student> map = list.stream().collect(Collectors.toMap(Student::getId, student -> student));
// 遍历打印结果
map.forEach((key, value) -> {
System.out.println("key: " + key + " value: " + value);
});
map value 为对象中的属性
Map<Integer, String> map = list.stream().collect(Collectors.toMap(Student::getId, Student::getName));
map.forEach((key, value) -> {
System.out.println("key: " + key + " value: " + value);
});
Collectors toSet
Set<String> result = Stream.of("aa", "bb", "cc", "aa").collect(HashSet::new, HashSet::add, HashSet::addAll);
//Collectors类中已经预定义好了toList,toSet,toMap,toCollection等方便使用的方法,所以以上代码还可以简化如下:
Set<String> result2 = Stream.of("aa", "bb", "cc", "aa").collect(Collectors.toSet());
Set<Integer> collectSet = Stream.of(1, 2, 3, 4).collect(Collectors.toSet());
System.out.println("collectSet: " + collectSet);
// 打印结果 collectSet: [1, 2, 3, 4]
Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
// collect toString
String str = stream.collect(Collectors.joining()).toString();
集合处理
从List中过滤出一个元素
User match = users.stream()
.filter((user) -> user.getId() == 1).findAny().get();
两集合寻找相同元素
// 求同时出现在老师集合和学生集合中的人数,name相同即视为同一个人
int size = teachers.stream()
.map(t -> students.stream().filter(s -> Objects.nonNull(t.getName()) && Objects.nonNull(s.getName()) && Objects.equals(t.getName(), s.getName())).findAny().orElse(null))
.filter(Objects::nonNull)
.collect(Collectors.toList())
.size(); // .collect(Collectors.toList()).size() == .count()
// 求同时出现在老师集合和学生集合中人的name集合,name相同即视为同一个人
List<String> names = teachers.stream()
.map(t -> students.stream().filter(s -> Objects.nonNull(t.getName()) && Objects.nonNull(s.getName()) && Objects.equals(t.getName(), s.getName())).findAny().orElse(null))
.filter(Objects::nonNull)
.map(r -> r.getName())
.collect(Collectors.toList());
分组
假设要得到按年龄分组的Map<Integer,List>,可以按这样写:
Map<Integer, List<User>> ageMap = userStream.collect(Collectors.toMap(User::getAge, Collections::singletonList, (a, b) -> {
List<User> resultList = new ArrayList<>(a);
resultList.addAll(b);
return resultList;
}));
Map<Integer, String> map = persons
.stream()
.collect(Collectors.toMap(
p -> p.age,
p -> p.name,
(name1, name2) -> name1 + ";" + name2));
System.out.println(map);
// {18=Max, 23=Peter;Pamela, 12=David}
Collectors groupingBy 分组
Map<Integer, List<User>> ageMap2 = userStream
.collect(Collectors.groupingBy(User::getAge));
还可以对集合按照多个属性分组。将多个字段拼接成一个新字段,然后再使用groupBy分组
Map<String, List<EntryDeliveryDetailywk>> detailmap = details.stream()
.collect(Collectors.groupingBy(this::fetchGroupKey));
private String fetchGroupKey(EntryDeliveryDetailywk detail){
return detail.getSkuId().toString()
+ detail.getItemsName()
+ detail.getWarehouseId().toString()
+ detail.getSupplierId().toString();
}
groupingBy 分组后操作
Collectors中还提供了一些对分组后的元素进行downStream处理的方法:
counting方法返回所收集元素的总数;
summing方法会对元素求和;
maxBy和minBy会接受一个比较器,求最大值,最小值;
mapping函数会应用到downstream结果上,并需要和其他函数配合使用;
Map<Boolean, Long> partiCount = Stream.of(1, 2, 3, 4)
.collect(Collectors.partitioningBy(it -> it.intValue() % 2 == 0,
Collectors.counting()));
System.out.println("partiCount: " + partiCount);
// 打印结果
// partiCount: {false=2, true=2}
Map<Integer, Long> sexCount = userStream.collect(Collectors.groupingBy(User::getSex,Collectors.counting()));
Map<Integer, Integer> ageCount = userStream.collect(Collectors.groupingBy(User::getSex,Collectors.summingInt(User::getAge)));
Map<Integer, Optional<User>> ageMax = userStream.collect(Collectors.groupingBy(User::getSex,Collectors.maxBy(Comparator.comparing(User::getAge))));
Map<Integer, List<String>> nameMap = userStream.collect(Collectors.groupingBy(User::getSex,Collectors.mapping(User::getName,Collectors.toList())));
groupingBy 更多例子
groupingBy 根据年龄来分组:
Map<Integer, List> peopleByAge = peoples.stream()
.filter(p -> p.age > 12).collect(Collectors.groupingBy(p -> p.age, Collectors.toList()));
Map<Integer, List<Person>> personsByAge = persons.stream().collect(Collectors.groupingBy(p -> p.age));
personsByAge.forEach((age, p) -> System.out.format("age %s: %s\n", age, p));
// age 18: [Max]
// age 23: [Peter, Pamela]
// age 12: [David]
groupingBy 根据年龄分组,年龄对应的键值List存储的为Person的姓名:
Map<Integer, List> peopleByAge = people.stream()
.collect(Collectors.groupingBy(p -> p.age, Collectors.mapping((Person p) -> p.name, Collectors.toList())));
//mapping即为对各组进行投影操作,和Stream的map方法基本一致。
groupingBy 根据姓名分组,获取每个姓名下人的年龄总和:
Map sumAgeByName = peoples.stream().collect(Collectors.groupingBy(p -> p.name, Collectors.reducing(0, (Person p) -> p.age, Integer::sum)));
/* 或者使用summingInt方法 */
sumAgeByName = peoples.stream().collect(Collectors.groupingBy(p -> p.name, Collectors.summingInt((Person p) -> p.age)));
groupingBy Boolean分组:
Map<Boolean, List<Integer>> collectGroup = Stream.of(1, 2, 3, 4)
.collect(Collectors.groupingBy(it -> it > 3));
System.out.println("collectGroup : " + collectGroup);
// 打印结果
// collectGroup : {false=[1, 2, 3], true=[4]}
Map.merge() 类似于分组之后sum
Map<String, Integer> studentScoreMap2 = new HashMap<>();
studentScoreList.forEach(studentScore -> studentScoreMap2.merge(
studentScore.getStuName(),
studentScore.getScore(),
Integer::sum));
Collectors partitioningBy
Collectors中还提供了partitioningBy方法,接受一个Predicate函数,该函数返回boolean值,用于将内容分为两组。
另外Collectors中还存在一个类似groupingBy的方法:partitioningBy,它们的区别是partitioningBy为键值为Boolean类型的groupingBy,这种情况下它比groupingBy更有效率。
例子
将userStream按性别分组*
假设User实体中包含性别信息getSex(),可以按如下写法:
Map<Boolean, List<User>> sexMap = userStream
.collect(Collectors.partitioningBy(item -> item.getSex() > 0));
partitioningBy 将数字的Stream分解成奇数集合和偶数集合。
Map<Boolean, List<Integer>> collectParti = Stream.of(1, 2, 3, 4)
.collect(Collectors.partitioningBy(it -> it % 2 == 0));
System.out.println("collectParti : " + collectParti);
// 打印结果
// collectParti : {false=[1, 3], true=[2, 4]}
排序
//按照自然顺序进行排序 如果要自定义排序sorted 传入自定义的 Comparator
list.stream()
.sorted()
.filter((s) -> s.startsWith("a"))
.forEach(System.out::println);
//对象排序比较 请重写对象的equals()和hashCode()方法
list.sorted((a, b) -> b.compareTo(a))
Collections.sort(names, (a, b) -> b.compareTo(a));
比较
Comparator<Person> comparator = (p1, p2) -> p1.firstName.compareTo(p2.firstName);
Person p1 = new Person("John", "Doe");
Person p2 = new Person("Alice", "Wonderland");
comparator.compare(p1, p2); // > 0
comparator.reversed().compare(p1, p2); // < 0
Collectors joining 拼接字符串
Collectors.joining 收集Stream中的值,该方法可以方便地将Stream得到一个字符串。joining函数接受三个参数,分别表示允(用以分隔元素)、前缀和后缀:
String names = peoples.stream().map(p->p.name).collect(Collectors.joining(","))
String strJoin = Stream.of("1", "2", "3", "4")
.collect(Collectors.joining(",", "[", "]"));
System.out.println("strJoin: " + strJoin);
// 打印结果
// strJoin: [1,2,3,4]
//字符串连接
String phrase = persons
.stream()
.filter(p -> p.age >= 18)
.map(p -> p.name)
.collect(Collectors.joining(" and ", "In Germany ", " are of legal age."));
System.out.println(phrase);
// In Germany Max and Peter and Pamela are of legal age.
List 转String
//java8 String.join 方式
List<String> webs = Arrays.asList("voidcc.com", "voidmvn.com", "voidtool.com");
//webs 必须是List<String>
String allwebs = String.join(",", webs);
System.out.println(allwebs);
//stream
List<String> webs = Arrays.asList("voidcc.com", "voidmvn.com", "voidtool.com");
String allwebs = webs.stream().collect(Collectors.joining(","));
System.out.println(allwebs);
聚合(使用collect将Stream转换成单个值)
Collectors分别提供了求平均值averaging、总数couting、最小值minBy、最大值maxBy、求和suming等操作。
聚合函数列表
maxBy和minBy允许用户按照某个特定的顺序生成一个值。
averagingDouble:求平均值,Stream的元素类型为double
averagingInt:求平均值,Stream的元素类型为int
averagingLong:求平均值,Stream的元素类型为long
counting:Stream的元素个数
maxBy:在指定条件下的,Stream的最大元素
minBy:在指定条件下的,Stream的最小元素
reducing: reduce操作
summarizingDouble:统计Stream的数据(double)状态,其中包括count,min,max,sum和平均。
summarizingInt:统计Stream的数据(int)状态,其中包括count,min,max,sum和平均。
summarizingLong:统计Stream的数据(long)状态,其中包括count,min,max,sum和平均。
summingDouble:求和,Stream的元素类型为double
summingInt:求和,Stream的元素类型为int
summingLong:求和,Stream的元素类型为long
Collectors.maxBy
Optional<Integer> collectMaxBy = Stream.of(1, 2, 3, 4)
.collect(Collectors.maxBy(Comparator.comparingInt(o -> o)));
System.out.println("collectMaxBy:" + collectMaxBy.get());
// 打印结果
// collectMaxBy:4
Collectors.averagingInt
计算集合的平均年龄
Double averageAge = persons
.stream()
.collect(Collectors.averagingInt(p -> p.age));
System.out.println(averageAge); // 19.0
Collectors.SummaryStatistics
假如你希望将流中结果聚合为一个总和、平均值、最大值、最小值,那么Collectors.summarizing(Int/Long/Double)就是为你准备的,它可以一次行获取前面的所有结果,其返回值为(Int/Long/Double)SummaryStatistics。
DoubleSummaryStatistics dss = people.collect(Collectors.summarizingDouble((Person p)->p.age));
double average=dss.getAverage();
double max=dss.getMax();
double min=dss.getMin();
double sum=dss.getSum();
double count=dss.getCount();
IntSummaryStatistics ageSummary = persons
.stream()
.collect(Collectors.summarizingInt(p -> p.age));
System.out.println(ageSummary);
// IntSummaryStatistics{count=4, sum=76, min=12, average=19.000000, max=23}
自定义 Collector
Collector<Person, StringJoiner, String> personNameCollector =
Collector.of(
() -> new StringJoiner(" | "), // supplier
(j, p) -> j.add(p.name.toUpperCase()), // accumulator
(j1, j2) -> j1.merge(j2), // combiner
StringJoiner::toString); // finisher
String names = persons
.stream()
.collect(personNameCollector);
System.out.println(names); // MAX | PETER | PAMELA | DAVID
【Java 基础】Collectors 使用小结的更多相关文章
- java基础知识小小结
java基础知识小总结 在一个独立的原始程序里,只能有一个 public 类,却可以有许多 non-public 类.此外,若是在一个 Java 程序中没有一个类是 public,那么该 Java 程 ...
- JAVA基础知识复习小结
集合 Set集合 Set集合的基本特征是元素不允许重复.HashSet不保存元素顺序,LinkedHashSet用链表保持元素的插入顺序,TreeSet可定制排序规则. HashSet的底层是用Has ...
- Java基础—String类小结
一.String类是什么 public final class String implements java.io.Serializable, Comparable<String>, Ch ...
- JAVA基础篇—Servlet小结
一.get请求和post请求的区别: 1.get请求是通过url传递参数,post请求是通过请求体传递参数的 2.get请求最多允许传递255个字符,对长度有限制,所以数据比较大的时候我们使用post ...
- Java基础系列-Collector和Collectors
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10748925.html 一.概述 Collector是专门用来作为Stream的coll ...
- 对最近java基础学习的一次小结
开头想了3分钟,不知道起什么名字好,首先内容有点泛,但也都是基础知识. 对之前所学的java基础知识做了个小结,因为我是跟着网上找的黑马的基础视频看跟着学的,10天的课程硬生生给我看了这么久,也是佛了 ...
- Java 基础--小结
Java 基础--小结 java基础 Java源程序(.java文件)——>java字节码文件(.class文件)——>由解释执行器(java.exe)将字节码文件加载到java虚拟机( ...
- java基础知识 + 常见面试题
准备校招面试之Java篇 一. Java SE 部分 1.1 Java基础 1. 请你解释Object若不重写hashCode()的话,hashCode()如何计算出来的? Object 的 hash ...
- Java基础知识【下】( 转载)
http://blog.csdn.net/silentbalanceyh/article/details/4608360 (最终还是决定重新写一份Java基础相关的内容,原来因为在写这一个章节的时候没 ...
- 万能的林萧说:一篇文章教会你,如何做到招聘要求中的“要有扎实的Java基础”。
来历 本文来自于一次和群里猿友的交流,具体的情况且听LZ慢慢道来. 一日,LZ在群里发话,"招人啦." 然某群友曰,"群主,俺想去." LZ回之,"你 ...
随机推荐
- 前端调试工具(DevTools)
前端调试工具(DevTools) 开启:F12 布局 切换PC和移动端 页面元素的快速测试技巧 保持元素的hover等状态:选中当前行点击右键 元素状态改变的监控技巧 触发断点后元素状态不会再改变,可 ...
- 10分钟简单学习net core集成jwt权限认证,快速接入项目落地使用
什么是JWT JSON Web Token(JWT)是目前最流行的跨域身份验证.分布式登录.单点登录等解决方案. JWT的官网地址:https://jwt.io/ 通俗地来讲,JWT是能代表用户身份的 ...
- 常见的yaml写法-CronJob
CronJob其实就是在Job的基础上加上了时间调度,我们可以:在给定的时间点运行一个任务,也可以周期性地在给定时间点运行.这个实际上和我们Linux中的crontab就非常类似了.一个CronJob ...
- 数据结构知识总结(STL整理)
重要知识点 1.基础知识 #include<bits/stdc++.h> //万能头文件 #include< algorithm > //包含sort函数 运用sort实现多关 ...
- Linux——搭建Samba(CIFS)服务器
一.Samba的基本概念 Samba服务:是提供基于Linux和Windows的共享文件服务,服务端和客户端都可以是Linux或Windows操作系统.可以基于特定的用户访问,功能比NFS更强大. S ...
- [cf700D]Huffman Coding on Segment
令$tot_{i}$为区间$[l,r]$中满足$a_{j}=i$的$j$的个数,将所有非0的$tot_{i}$取出,得到可重集$S$ 显然,有以下贪心:不断取出$S$中最小的两个元素,删除这两个元素并 ...
- [noi707]LP
(以下用$Sa=\sum_{j=1}^{i}xi\cdot ai$,Sb和Sc同理)令f[i][x]表示前i个数,$Sa\le x\le Sb$时最小的Sc考虑第i个数是否选择,可以得到递推式$f[i ...
- appScan安全软件的使用
1.点击文件,新建 2.常规扫描 3.点击下一步 4.输入需要扫描的网站 5.下一步,如果有账号 密码可以使用记录. 6.选择缺省值,下一步 7.启动全面扫描.
- 洛谷 P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I(分块+卡常)
洛谷题面传送门 zszz,lxl 出的 DS 都是卡常题( 首先由于此题强制在线,因此考虑分块,我们那么待查询区间 \([l,r]\) 可以很自然地被分为三个部分: 左散块 中间的整块 右散块 那么这 ...
- DP 做题记录 II.
里面会有一些数据结构优化 DP 的题目(如 XI.),以及普通 DP. *I. P3643 [APIO2016]划艇 题意简述:给出序列 \(a_i,b_i\),求出有多少序列 \(c_i\) 满足 ...