用流收集数据
2018-05-26 本文已影响19人
小鱼嘻嘻
- 找出流中最大和最小元素
List<Dish> dishes = Arrays.asList(new Dish(), new Dish(), new Dish());
Dish max = dishes.stream().collect(
Collectors.maxBy(
Comparator.comparing(Dish::getName))).get();
Dish min = dishes.stream().collect(
Collectors.minBy(
Comparator.comparing(Dish::getName))).get();
Dish mmin = dishes.stream().min(Comparator.comparing(Dish::getName)).get();
Dish mmax = dishes.stream().max(Comparator.comparing(Dish::getName)).get();
- 汇总
//汇总
Integer categaries = dishes.stream().collect(Collectors.summingInt(Dish::getCategary));
//summarizingInt 是一个工厂 IntSummaryStatistics返回 max min count sum
IntSummaryStatistics summaryStatistics = dishes.stream().collect(Collectors.summarizingInt(Dish::getCategary));
summaryStatistics.getMax();
summaryStatistics.getMin();
summaryStatistics.getSum();
summaryStatistics.getAverage();
summaryStatistics.getCount();
- 字符串连接
joining工厂方法返回的收集器会把对流中每一个对象应用tostring方法得到的字符串连接成一个新的字符串
//字符串操作
List<String> strings = Arrays.asList("hello", "join", "world");
String s = strings.stream().collect(Collectors.joining());
String collect = strings.stream().collect(Collectors.joining(","));
- 分组
一个常见的数据库操作是根据一个或者多个属性对集合中的项目进行分组。
//按照菜肴类型分组
Map<String, List<Dish>> typeMaps = dishes.stream().collect(Collectors.groupingBy(Dish::getType));
groupingBy接收一个Function,这个function就是分组函数,按照我们指定的规则进行分组。这个分组函数可以是方法引用也可以是一段lambda表达式。
- 多级分组
//多级分组 先根据类型分组,分组完成之后再按照名称分组
Map<String, Map<String, List<Dish>>> groupMaps = dishes.stream().collect(
Collectors.groupingBy(dish -> dish.getType(),
Collectors.groupingBy(dish -> dish.getName())));
groupingBy(function,collector)也就是说groupingBy是可以再接收一个collector,这个collector当然可以再次进行分组。
- 分区
分区的好处在于保留了分区函数返回true和false的两套流元素列表。
//分区
Map<Boolean, List<Dish>> partionMap = dishes.stream().collect(
Collectors.partitioningBy(dish -> dish.getType().equals("meat")));
//分区多级函数
Map<Boolean, Optional<Dish>> meat = dishes.stream().collect(
Collectors.partitioningBy(dish -> dish.getType().equals("meat"),
Collectors.maxBy(Comparator.comparing(Dish::getCategary))));
实际工作中很少用到。
收集器接口
public interface Collector<T,A,R> {
Supplier<A> supplier();
BiConsumer<A,R> accumulator();
Function<A,R> finisher();
BinaryOperator<A> combiner();
Set<Characteristics> characteristics();
}
- T 是流中要收集的项目的泛型
- A是累加器的类型,累加器实在收集过程中用于累计部分结果的对象
- R 是收集操作得到的对象
理解collector接口申明的方法
- 建立新的结果容器: supplier
supplier方法必须返回一个结果为空的Supplier,也就是一个无参函数,在调用它是会返回一个空的累加器实例。
public Supplier<List<T>> supplier() {
return ()->new ArrayList<T>();
}
- 将元素添加到结果容器: accumulator
accumulator方法会返回执行规约操作的函数
public BiComsumer<List<T>,T> accumulator() {
return (list,item)->list.add(item);
}
- 对结果容器应用最终转换:finisher
在遍历完流之后,finisher方法必须返回在累积过程的最后要调用的一个函数,以便将累加器对象转换为整个集合操作的最终结果。
public Function<List<T>,List<T>> finisher() {
return Function.identity();
}
- 合并两个结果容器: combiner
combiner返回一个供规约操作使用的函数,它定义了对流的各个子部分进行并行处理,各个子部分规约所得的累加器要如何合并。
public BinaryOperator<List<T>> combiner() {
return (list1,list2)->{
list1.addAll(list2);
return list1;
}
}
- characteristics
characteristics 会返回一个不可变的characteristics集合,它定义了收集器的行为。
unordered 规约结果不接受流中项目的遍历和累积顺序的影响
concurrent 可以多线程同时调用
indentity_finish 表明是一个恒等函数