#Collectors 使用 在之前篇章中,我们探讨了、、的使用。现在拿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) { ListuserList = constructUserList(); //使用JDK8 按照名字分组 Map > userMaps = userList.stream().collect(Collectors.groupingBy(u -> u.getName())); //按照密码分组 Map > 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 > userJdk7Map = new HashMap >(); //按照名字分组 for (User u : userList) { if (userJdk7Map.containsKey(u.getName())) {//如果map中已经存在则add 到groupList中 List groupTempUserList = userJdk7Map.get(u.getName()); groupTempUserList.add(u); }else{//增加一个新的 List groupTempUserList = new ArrayList (); groupTempUserList.add(u); userJdk7Map.put(u.getName(), groupTempUserList); } } //按照密码分组 大写略 参考名字分组 //jdk7 打印 for (Map.Entry > 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 constructUserList() { List userList = new ArrayList (); 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----------password0password1---------------- group by user name = name0----------password0password1---------------- group by user password = password0----------name0name1---------------- group by user password = password1----------name0name1---------------- jdk7 group by user name = name1----------password0password1---------------- jdk7 group by user name = name0----------password0password1
如果感兴趣,可以点击进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) { ListuserList = constructUserList(); //使用JDK8 提取所有名字 List userStrList = userList.stream().map(User::getName).collect(Collectors.toList()); //把名字提取出来,并转化成name set Set userNameSet = userList.stream().map(User::getName).collect(Collectors.toSet()); //转化成 结构的map,注意: key 不能重复,使用distinct去重复 Map userNameMap = userList.stream().distinct().collect(Collectors.toMap(u -> u.getName(), u -> u.getPassword())); //提取成 Map Map userMap = userList.stream().distinct().collect(Collectors.toMap(u -> u.getName(), Function.identity())); //提取成 Map 合并 Map 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 constructUserList() { List userList = new ArrayList (); 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 -------------name0name0name1name1name2name2name3name3---------------打印 set -------------name3name2name1name0---------------打印 map -------------name3---password3name2---password2name1---password1name0---password0---------------打印 user map -------------name3---password3name2---password2name1---password1name0---password0---------------打印 userMergeDulicateMap -------------name3---password3,password3name2---password2,password2name1---password1,password1name0---password0,password0
##3. Collectors API使用
下面例子介绍部分collectors API的使用,主要有:maxBy、joining、counting、summingInt、partitioningBy、summarizingInt 的使用,如果感兴趣可以琢磨一下collectors API的内部使用,理解一下downstream ,和前面章节介绍的 就很容易融入到自己代码中.
public class Jdk8_collector_operation_test { private static class User { private String name; private String password; //省略getter setter } public static void main(String[] args) { ListuserList = 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 groupNameCount = userList.stream().collect(Collectors.groupingBy(User::getName, Collectors.counting())); //6.partitioningBy 分片 根据Predicate条件分片 Map > 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 constructUserList() { List userList = new ArrayList (); 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集合个数:8name3 ---打印分组元素个数--- 2name2 ---打印分组元素个数--- 2name1 ---打印分组元素个数--- 2name0 ---打印分组元素个数--- 2false ---打印分片元素--- name0name0name2name2name3name3true ---打印分片元素--- name1name1------汇总统计----平均值:9.0------汇总统计----元素个数:8------汇总统计----最小值:9------汇总统计----最大值:9------汇总统计----累加:72
JDK8 API使用很多时候耐心点看就能明白作者这样设计的巧妙,还是要多用,即使一开始不熟悉,用起来很别扭,应该用着用着就爱上了。