2019独角兽企业重金招聘Python工程师标准>>>
#Collectors 使用 在之前篇章中,我们探讨了Lambdas、函数式接口编程、Stream的使用。现在拿collectors 耍耍.
Collectors是一个reduce操作,通过collectors 可以把一个结合转换成另外一个集合collection,Map, 或者一个值。
来看看collectors能干什么:
##1.分组 groupby
public class Jdk8_collector_groupby_test {
private static class User {
private String name;
private String password;
//省略getter setter
}
public static void main(String[] args) {
List<User> userList = constructUserList();
//使用JDK8 按照名字分组
Map<String, List<User>> userMaps = userList.stream().collect(Collectors.groupingBy(u -> u.getName()));
//按照密码分组
Map<String, List<User>> userPasswordMaps = userList.stream().collect(Collectors.groupingBy(u -> u.getPassword()));
userMaps.forEach((key, groupUser) -> {
System.out.println("---------------- group by user name = " + key + "----------");
groupUser.forEach(u -> System.out.println(u.getPassword()));
});
userPasswordMaps.forEach((key, groupUser) -> {
System.out.println("---------------- group by user password = " + key + "----------");
groupUser.forEach(u -> System.out.println(u.getName()));
});
//上面的例子想想用JKD7写,表示博主很懒
Map<String, List<User>> userJdk7Map = new HashMap<String, List<User>>();
//按照名字分组
for (User u : userList) {
if (userJdk7Map.containsKey(u.getName())) {//如果map中已经存在则add 到groupList中
List<User> groupTempUserList = userJdk7Map.get(u.getName());
groupTempUserList.add(u);
}else{//增加一个新的
List<User> groupTempUserList = new ArrayList<User>();
groupTempUserList.add(u);
userJdk7Map.put(u.getName(), groupTempUserList);
}
}
//按照密码分组 大写略 参考名字分组
//jdk7 打印
for (Map.Entry<String, List<User>> entry : userJdk7Map.entrySet()) {
System.out.println("---------------- jdk7 group by user name = " + entry.getKey() + "----------");
for (User user : entry.getValue()) {
System.out.println( user.getPassword());
}
}
}
/**
* 构造一个用户列表
* @return
*/
private static List<User> constructUserList() {
List<User> userList = new ArrayList<User>();
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
User u = new User();
u.setPassword("password" + j);
u.setName("name" + i);
userList.add(u);
}
}
return userList;
}
}
运行结果:
---------------- group by user name = name1----------
password0
password1
---------------- group by user name = name0----------
password0
password1
---------------- group by user password = password0----------
name0
name1
---------------- group by user password = password1----------
name0
name1
---------------- jdk7 group by user name = name1----------
password0
password1
---------------- jdk7 group by user name = name0----------
password0
password1
如果感兴趣,可以点击进Collectors.groupingBy看看,参数就是一个Function,根据条件进行分组。
##2. 最经常使用的,集合转变成其他集合
public class Jdk8_collector_reduce_test {
private static class User {
private String name;
private String password;
//getter setter
}
public static void main(String[] args) {
List<User> userList = constructUserList();
//使用JDK8 提取所有名字
List<String> userStrList = userList.stream().map(User::getName).collect(Collectors.toList());
//把名字提取出来,并转化成name set
Set<String> userNameSet = userList.stream().map(User::getName).collect(Collectors.toSet());
//转化成<name, password> 结构的map,注意: key 不能重复,使用distinct去重复
Map<String, String> userNameMap = userList.stream().distinct().collect(Collectors.toMap(u -> u.getName(), u -> u.getPassword()));
//提取成 Map<name, User>
Map<String, User> userMap = userList.stream().distinct().collect(Collectors.toMap(u -> u.getName(), Function.identity()));
//提取成 Map<name, String> 合并
Map<String, String> userMergeDulicateMap = userList.stream()
.collect(Collectors.toMap(User::getName, User::getPassword, (t1, t2) ->{
return t1 + "," + t2;
}));
System.out.println("---------------打印 list -------------");
userStrList.forEach(System.out::println);
System.out.println("---------------打印 set -------------");
userNameSet.forEach(System.out::println);
System.out.println("---------------打印 map -------------");
userNameMap.forEach((key, val) -> {
System.out.println(key + "---" + val);
});
System.out.println("---------------打印 user map -------------");
userMap.forEach((key, val) -> {
System.out.println(key + "---" + val.getPassword());
});
System.out.println("---------------打印 userMergeDulicateMap -------------");
userMergeDulicateMap.forEach((key, val) -> {
System.out.println(key + "---" + val);
});
}
/**
* 构造一个用户列表
*
* @return
*/
private static List<User> constructUserList() {
List<User> userList = new ArrayList<User>();
for (int i = 0; i < 4; i++) {
User u = new User();
u.setPassword("password" + i);
u.setName("name" + i);
userList.add(u);
userList.add(u);
}
return userList;
}
}
运行结果:
---------------打印 list -------------
name0
name0
name1
name1
name2
name2
name3
name3
---------------打印 set -------------
name3
name2
name1
name0
---------------打印 map -------------
name3---password3
name2---password2
name1---password1
name0---password0
---------------打印 user map -------------
name3---password3
name2---password2
name1---password1
name0---password0
---------------打印 userMergeDulicateMap -------------
name3---password3,password3
name2---password2,password2
name1---password1,password1
name0---password0,password0
##3. Collectors API使用
下面例子介绍部分collectors API的使用,主要有:maxBy、joining、counting、summingInt、partitioningBy、summarizingInt 的使用,如果感兴趣可以琢磨一下collectors API的内部使用,理解一下downstream ,和前面章节介绍的 predicate、function、consumer 就很容易融入到自己代码中.
public class Jdk8_collector_operation_test {
private static class User {
private String name;
private String password;
//省略getter setter
}
public static void main(String[] args) {
List<User> userList = constructUserList();
//1.maxBy求最大值
User user = userList.stream().collect(Collectors.collectingAndThen(
Collectors.maxBy((t1, t2) ->t1.getPassword().length() - t2.getPassword().length()), Optional::get));
//2.joining 合并,通过分隔符“,”合并用户名称
String userName = userList.stream().map(User::getName).collect(Collectors.joining(","));
//3.summingInt 统计总和
int totalNameLen = userList.stream().map(User::getName).collect(Collectors.summingInt(String::length));
//4.counting 集合个数
Long count = userList.stream().map(User::getName).collect(Collectors.counting());
//5.groupingBy 分组, counting统计元素个数,按照名字分组,并统计分组元素个数
Map<String, Long> groupNameCount = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.counting()));
//6.partitioningBy 分片 根据Predicate条件分片
Map<Boolean, List<User>> partitioningMap = userList.stream()
.collect(Collectors.partitioningBy(u -> u.getPassword().indexOf("1") >= 0, Collectors.toList()));
//7.summarizingInt 对数据的汇总统计 返回一个统计类IntSummaryStatistics
IntSummaryStatistics intSummaryStatistics = userList.stream().map(User::getPassword)
.collect(Collectors.summarizingInt(String::length));
System.out.println( "password最大长度的:" + user.getName());
System.out.println("所用用户名:" + userName);
System.out.println("所有用户名长度:" + totalNameLen);
System.out.println("集合个数:" + count);
groupNameCount.forEach((key, val) -> {
System.out.println(key + " ---打印分组元素个数--- " + val);
});
partitioningMap.forEach((key, val) -> {
System.out.println(key + " ---打印分片元素--- ");
val.forEach(u -> {
System.out.println( u.getName() );
});
});
System.out.println("------汇总统计----平均值:" + intSummaryStatistics.getAverage());
System.out.println("------汇总统计----元素个数:" + intSummaryStatistics.getCount());
System.out.println("------汇总统计----最小值:" + intSummaryStatistics.getMin());
System.out.println("------汇总统计----最大值:" + intSummaryStatistics.getMax());
System.out.println("------汇总统计----累加:" + intSummaryStatistics.getSum());
}
/**
* 构造一个用户列表
*
* @return
*/
private static List<User> constructUserList() {
List<User> userList = new ArrayList<User>();
for (int i = 0; i < 4; i++) {
User u = new User();
u.setPassword("password" + i);
u.setName("name" + i);
userList.add(u);
userList.add(u);
}
return userList;
}
}
返回结果:
password最大长度的:name0
所用用户名:name0,name0,name1,name1,name2,name2,name3,name3
所有用户名长度:40
集合个数:8
name3 ---打印分组元素个数--- 2
name2 ---打印分组元素个数--- 2
name1 ---打印分组元素个数--- 2
name0 ---打印分组元素个数--- 2
false ---打印分片元素---
name0
name0
name2
name2
name3
name3
true ---打印分片元素---
name1
name1
------汇总统计----平均值:9.0
------汇总统计----元素个数:8
------汇总统计----最小值:9
------汇总统计----最大值:9
------汇总统计----累加:72
JDK8 API使用很多时候耐心点看就能明白作者这样设计的巧妙,还是要多用,即使一开始不熟悉,用起来很别扭,应该用着用着就爱上了。