Java 8
流的新类java.util.stream.Collectors
实现了java.util.stream.Collector
接口,同时又提供了大量的方法对流 (stream
) 的元素执行map
and
reduce
操作,或者统计操作。
Collectors.collectingAndThen()
函数应该最像 map and reduce
了,它可接受两个参数,第一个参数用于 reduce
操作,而第二参数用于 map
操作。
也就是,先把流中的所有元素传递给第一个参数,然后把生成的集合传递给第二个参数来处理。
例如下面的代码
[1,2,3,4]
这个集合传递给 v -> v * 2
lambda表达式,计算得出结果为[2,4,6,8]
[2,4,6,8]
传递给 Collectors.averagingLong
表达式,计算得出 5.0
s -> s * s
lambda表达式,计算得到结果为 25.0
@Test
public void collectingAndThenExample() {
List<Integer> list = Arrays.asList(1, 2, 3, 4);
Double result = list.stream().collect(Collectors.collectingAndThen(Collectors.averagingLong(v -> {
System.out.println("v--" + v + "--> " + v * 2);
return v * 2;
}),
s -> {
System.out.println("s--" + s + "--> " + s * s);
return s * s;
}));
System.out.println(result);
}
v--1--> 2
v--2--> 4
v--3--> 6
v--4--> 8
s--5.0--> 25.0
25.0
一点唠叨:
Collectors.averagingDouble()
来说,方法体只执行一次。Collectors.averagingDouble()
来说,方法体做出了优化Collectors.averagingDouble()
来说,这个没有坑Collectors.averagingDouble()
,因为Collectors.averagingDouble()
有坑,有坑,有坑public static <T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher)
应用:根据list中对象某属性进行去重
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("111", 132774, 12, "1"));
studentList.add(new Student("123", 13556, 15, "1"));
studentList.add(new Student("1146", 13165142, 16, "1"));
studentList.add(new Student("111", 136542, 14, "2"));
studentList.add(new Student("141321", 5641542, 15, "2"));
studentList.add(new Student("1454135", 2222542, 15, "2"));
List<Student> collect = studentList.stream().collect(
Collectors.collectingAndThen(
Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(Student::getStuName))),
ArrayList::new));
System.out.println(collect.size());
// 等效处理 此处在treeSet构造方法中传入比较器 可以自定义比较器传入
TreeSet<Student> treeSet = new TreeSet<>(Comparator.comparing(Student::getStuName));
treeSet.addAll(studentList);
List<Student> treeCollect = new ArrayList<>(treeSet);
System.out.println(treeCollect.size());
output
Student{stuName='111', stuId=132774, stuAge=12, classNum='1'}
Student{stuName='1146', stuId=13165142, stuAge=16, classNum='1'}
Student{stuName='123', stuId=13556, stuAge=15, classNum='1'}
Student{stuName='141321', stuId=5641542, stuAge=15, classNum='2'}
Student{stuName='1454135', stuId=2222542, stuAge=15, classNum='2'}
ArrayList(Collection c)
,所以就是把Collector downstream
的结果再给到Function finisher
去处理,用toCollection收集结果Map<String, List<String>> ruleMap1 = ruleList.stream().
.collect(Collectors.groupingBy(Rule::getId,
Collectors.mapping(Rule::getRuleName, Collectors.toList())));
Map<String, Rule> ruleMap = ruleList.stream().
.collect(Collectors.groupingBy(Rule::getId,
Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));