Java Stream流式处理集合-去重排序分组转换操作
Java Stream流式处理集合 去重排序分组转换操作
工作中Stream流操作集合 很方便快捷,以下是记录常用的去重排序分组转换操作
去重
1.首先使用Integer 和String 类型集合 进行操作 代码如下:
1 | //定义两组数据类型集合 |
2.定义实体Person及组装数据:
1 | List<Person> list = new ArrayList<>(); |
按名字去重后展示
1 | list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))) |
执行输出:
Person(name=chensan, age=25, sex=男)
Person(name=lisi, age=22, sex=男)
Person(name=liuliu, age=22, sex=女)
Person(name=zhangsan, age=20, sex=男)
Person(name=zhaosi, age=22, sex=男)
按名字 年龄去重
1 | list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> |
执行输出:
Person(name=chensan, age=25, sex=男)
Person(name=lisi, age=22, sex=男)
Person(name=lisi, age=23, sex=女)
Person(name=lisi, age=24, sex=女)
Person(name=liuliu, age=22, sex=女)
Person(name=zhangsan, age=20, sex=男)
Person(name=zhaosi, age=22, sex=男)
Person(name=zhaosi, age=40, sex=男)
按名字 年龄 性别去重
1 | list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> |
执行输出:
Person(name=chensan, age=25, sex=男)
Person(name=lisi, age=22, sex=男)
Person(name=lisi, age=23, sex=女)
Person(name=lisi, age=24, sex=女)
Person(name=liuliu, age=22, sex=女)
Person(name=zhangsan, age=20, sex=男)
Person(name=zhaosi, age=22, sex=男)
Person(name=zhaosi, age=40, sex=男)
排序
根据年龄排序 再根据名字排序 从小到大
1 | list.stream().sorted(Comparator.comparing(Person::getAge).thenComparing(Person::getName)).forEach(System.out::println); |
执行输出:
Person(name=zhangsan, age=20, sex=男)
Person(name=lisi, age=22, sex=男)
Person(name=liuliu, age=22, sex=女)
Person(name=zhaosi, age=22, sex=男)
Person(name=lisi, age=23, sex=女)
Person(name=lisi, age=24, sex=女)
Person(name=chensan, age=25, sex=男)
Person(name=zhaosi, age=40, sex=男)
根据年龄排序 再根据名字排序 从大到小
1 | list.stream().sorted(Comparator.comparing(Person::getAge,Comparator.reverseOrder())).forEach(System.out::println); |
执行输出:
Person(name=zhaosi, age=40, sex=男)
Person(name=chensan, age=25, sex=男)
Person(name=lisi, age=24, sex=女)
Person(name=lisi, age=23, sex=女)
Person(name=lisi, age=22, sex=男)
Person(name=zhaosi, age=22, sex=男)
Person(name=liuliu, age=22, sex=女)
Person(name=zhangsan, age=20, sex=男)
当存在字段为null时,执行会报空指针异常,此时可用Comparator.nullsLast 或Comparator.nullsFirst 比较器 将null值数据放到最前或最后
如:添加 一组年龄为空的数据
list.add(new Person(“ben”, null, “女”));
根据年龄排序 存在age字段为空时 ,null值排在最前面 后根据age倒序展示
1 | list.stream().sorted(Comparator.comparing(Person::getAge,Comparator.nullsFirst(Collections.reverseOrder()))).forEach(System.out::println); |
执行输出:
Person(name=ben, age=null, sex=女)
Person(name=zhaosi, age=40, sex=男)
Person(name=chensan, age=25, sex=男)
Person(name=lisi, age=24, sex=女)
Person(name=lisi, age=23, sex=女)
Person(name=lisi, age=22, sex=男)
Person(name=zhaosi, age=22, sex=男)
Person(name=liuliu, age=22, sex=女)
Person(name=zhangsan, age=20, sex=男)
根据年龄排序 存在age字段为空时 ,null值排在最后面 后根据age倒序展示
1 | list.stream().sorted(Comparator.comparing(Person::getAge,Comparator.nullsLast(Collections.reverseOrder()))).forEach(System.out::println); |
执行输出:
Person(name=zhaosi, age=40, sex=男)
Person(name=chensan, age=25, sex=男)
Person(name=lisi, age=24, sex=女)
Person(name=lisi, age=23, sex=女)
Person(name=lisi, age=22, sex=男)
Person(name=zhaosi, age=22, sex=男)
Person(name=liuliu, age=22, sex=女)
Person(name=zhangsan, age=20, sex=男)
Person(name=ben, age=null, sex=女)
获取年龄最大的人的名字
1 | System.out.println(list.stream().max(Comparator.comparing(Person::getAge)).orElse(new Person()).getName()); |
分组统计
根据名字_性别 分组
1 | list.stream().collect(Collectors.groupingBy(x->x.getName()+"_"+x.getSex())).forEach((x,y)-> System.out.println(x+"="+y)); |
执行输出:
lisi_男=[Person(name=lisi, age=22, sex=男)]
liuliu_女=[Person(name=liuliu, age=22, sex=女)]
chensan_男=[Person(name=chensan, age=25, sex=男)]
zhaosi_男=[Person(name=zhaosi, age=22, sex=男), Person(name=zhaosi, age=40, sex=男)]
lisi_女=[Person(name=lisi, age=24, sex=女), Person(name=lisi, age=23, sex=女)]
zhangsan_男=[Person(name=zhangsan, age=20, sex=男)]
根据姓名 统计数量
1 | list.stream().collect(Collectors.groupingBy(Person::getName,Collectors.counting())).forEach((x, y)-> System.out.println(x+"="+y)); |
执行输出:
chensan=1
lisi=3
zhaosi=2
zhangsan=1
liuliu=1
根据名字分组 统计年龄总和
1 | list.stream().collect(Collectors.groupingBy(Person::getName, Collectors.summingInt(Person::getAge))).forEach((x,y)-> System.out.println(x+"="+y)); |
执行输出:
chensan=25
lisi=69
zhaosi=62
zhangsan=20
liuliu=22
转换Map
按名字作为键 值为年龄最大的 转换成Map
1 | list.stream().collect(Collectors.toMap(Person::getName,Function.identity(), BinaryOperator.maxBy(Comparator.comparing(Person::getAge)))).forEach((x,y)-> |
执行输出:
chensan=Person(name=chensan, age=25, sex=男)
lisi=Person(name=lisi, age=24, sex=女)
zhaosi=Person(name=zhaosi, age=40, sex=男)
zhangsan=Person(name=zhangsan, age=20, sex=男)
liuliu=Person(name=liuliu, age=22, sex=女)
按名字作为键 值为性别以分号追加展示 转换成Map
1 | list.stream().collect(Collectors.toMap(Person::getName, Person::getSex, (m, n) -> m + ";" + n)).forEach((x, y) -> System.out.println(x + "=" + y)); |
执行输出:
chensan=男
lisi=男;女;女
zhaosi=男;男
zhangsan=男
liuliu=女
注:如果使用两个参数的toMap方法时,若存在键重复时会报 “ Duplicate key ” 错
1 | list.stream().collect(Collectors.toMap(Person::getName, Person::getSex)).forEach((x, y) -> System.out.println(x + "=" + y)); |
执行输出:
Exception in thread “main” java.lang.IllegalStateException: Duplicate key zhaosi (attempted merging values 男 and 男)
at java.base/java.util.stream.Collectors.duplicateKeyException(Collectors.java:133)
at java.base/java.util.stream.Collectors.lambda$uniqKeysMapAccumulator$1(Collectors.java:180)
at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
Java8相关资料参考文档:
Java 8 教程汇总 https://wizardforcel.gitbooks.io/java8-tutorials/content/index.html
Java8简明教程 https://wizardforcel.gitbooks.io/modern-java
Java8新特性探究 https://wizardforcel.gitbooks.io/java8-new-features/content/






