java8 stream流 collect

分手后的思念是犯贱 2022-06-10 04:40 313阅读 0赞
  1. 流的收集器非常有用。可用于将流元素归约和汇总为一个值 ,元素分组,元素分区。

1.归约与汇总

  1. 静态导入java.util.stream.Collectors.\*

1.1求值

  1. Collectors.maxByCollectors.minBy,来计算流中的最大或最小值。参数为Comparator
  2. Optional<A> max = Stream.of(new A(4),new A(2),new A(8)).collect(maxBy(comparing(A::getNum)));
  3. Optional<A> min = Stream.of(new A(4),new A(2),new A(8)).collect(minBy(comparing(A::getNum)));
  4. max.ifPresent(a->System.out.println(a.getNum()));
  5. min.ifPresent(a->System.out.println(a.getNum()));
  6. Collectors.summingInt 。求和,输出int 。还有summingLongSummingDouble方法。
  7. int sum = Stream.of(new A(4),new A(2),new A(8)).collect(summingInt(A::getNum));<!--输出14-->
  8. Collectors.averagingInt 求平均值。还有averagingLongaveragingDouble
  9. Double ave = Stream.of(new A(4),new A(2),new A(8)).collect(averagingInt(A::getNum));
  10. summarizingInt方法返回的值中包含了最大值,最小值,和,平均值,数量。还有summarizingLongsummarizingDouble
  11. IntSummaryStatistics iss = Stream.of(new A(4),new A(2),new A(8)).collect(summarizingInt(A::getNum));

1.2连接字符串

  1. joining工厂方法返回的收集器会把对流中每一个对象应用toString方法得到的所有字符串连接成一个字符串。joining参数为分隔符。
  2. List<String> list = Arrays.asList("hello","world","stream");
  3. String s = list.stream().collect(joining(", "));
  4. reducing方法,可以有初始值,转换函数,累加函数。
  5. List<A> list = Arrays.asList(new A(5),new A(2),new A(3));
  6. int i = list.stream().collect(reducing(0, A::getNum,(a,b)->a+b));

2.分组

  1. Collectors.groupingBy可以用于分组。返回Map类型。参数为function。还有个重载方法参数为FunctionCollectorCollector参数就是对前面分完组的内容进行操作。
  2. List<A> list = Arrays.asList(new A("tom",22),new A("james",22),new A("jack",3));
  3. Map<String, List<A>> map1 = list.stream().collect(groupingBy(A::getName));
  4. 多级分组:
  5. List<A> list = Arrays.asList(new A("tom",22),new A("tom",15),new A("jack",3));
  6. Map<String, Map<String,List<A>>> map2 = list.stream().collect(
  7. groupingBy(A::getName,groupingBy(a->{if(a.getAge()<18)return "child";
  8. else return "adult";})));
  9. 判断每个分组有多少数量:
  10. List<A> list = Arrays.asList(new A("tom",22),new A("tom",15),new A("jack",3));
  11. Map<String, Long> map2 = list.stream().collect(
  12. groupingBy(A::getName,counting()));
  13. 得到每个分组年龄最大的那个人:
  14. List<A> list = Arrays.asList(new A("tom",22),new A("tom",15),new A("jack",3));
  15. Map<String, Optional<A>> map2 = list.stream().collect(
  16. groupingBy(A::getName,maxBy(comparing(A::getAge))));
  17. Collectors.collectingAndThen 方法可以把结果转换为另一种类型。参数为collectorfunction
  18. List<A> list = Arrays.asList(new A("tom",22),new A("tom",15),new A("jack",3));
  19. Map<String, A> map2 = list.stream().collect(
  20. groupingBy(A::getName,collectingAndThen(maxBy(comparing(A::getAge)), Optional::get)));
  21. mapping方法参数为functionCollector
  22. List<A> list = Arrays.asList(new A("tom",22),new A("tom",15),new A("jack",3));
  23. Map<String, HashSet<Integer>> map2 = list.stream().collect(
  24. groupingBy(A::getName,mapping(A::getAge, toCollection(HashSet::new))));
  25. Collectors返回集合的方法有toList(),toSet(),toMap(),toConcurrentMap()方法。

3.分区

  1. 分区就是分组的特殊情况,分区的键值为boolean类型。参数为predicate。还有一个重载方法参数为predicateCollector
  2. List<A> list = Arrays.asList(new A("tom",22),new A("tom",15),new A("jack",3));
  3. Map<Boolean,List<A>> map2 = list.stream().collect(partitioningBy(a->a.getAge()>18));
  4. 分区的好处在于保留了truefalse的两套列表。

4.Collector接口

Collector接口:

  1. public interface Collector<T, A, R> {
  2. Supplier<A> supplier();
  3. BiConsumer<A, T> accumulator();
  4. BinaryOperator<A> combiner();
  5. Function<A, R> finisher();
  6. Set<Characteristics> characteristics();
  7. }
  8. T为收集对象的泛型,A是累加器的类型, 累加器是在收集过程中用于累积部分结果的对象。 R是返回对象的类型。
  9. supplier方法定义累加器类型。
  10. accmulator方法把元素添加到累加器。
  11. combiner方法合并两个结果容器。
  12. finisher方法把累加器转为结果容器。
  13. characteristics方法定义收集器行为,比如流是否可以并行归约,以及可以使用那些优化。

5.并行流

  1. 可以用parallelStream方法把集合转为并行流。并行流就是把内容分为几个数据块然后用不同的线程去执行这些数据块。这样就可以使用多核处理器的所有内核。
  2. parallel()方法可以把流转为并行流。sequential()方法可以把并行流转为顺序流。
  3. 使用并行流的建议:
  4. 1.并行流不一定比顺序流快,需要检查流的性能。
  5. 2.最好不要装箱拆箱,可以的话使用IntStream这样的流。
  6. 3.有些操作并行流就会比顺序流慢,比如findFirst等等需要元素顺序的。
  7. 4.考虑流的操作在流水线的总计算成本 N为元素总数,Q为元素在流水线中的处理成本,Q越大用并行流的效率可能更高。
  8. 5.小的数据量不要用并行流。
  9. 6.考虑流背后的数据结构是否易于分解。数组就比较好分解,链表就不好分解,range方法产生的流比较好分解,iterate不好分解。

发表评论

表情:
评论列表 (有 0 条评论,313人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java8——Stream

    `Stream`是数据渠道,用于操作集合、数组等生成的元素序列。 `Stream`操作的三个步骤: 创建Stream 中间操作 终止操作 一、获取st

    相关 Java8 Stream操作

    java8中的流式操作是一个很重要的内容 ![stream主要流操作][stream] 上图列出了stream主要流操作,我们可以看到,其实流操作可以类比我们的sql