0%

在 Stream 的处理过程中,我们有时会遇到写 if/else 的情况,而带有 if/else 的逻辑通常会有些长。在写 lambda 表达式时,我们又需要尽量写简洁的语句。那么,对于含有判断语句的情况,该怎么处理?

针对 if/else 通常有以下几种场景:

  1. if
  2. if else
  3. if else if else if else
  4. 嵌套 if/else
阅读全文 »

JDK 内置的收集器基础上已经可以满足我们的日常开发需求,但有时候我们也可能会遇到不满足的情况,这种情况下我们可以自定义收集器来完成我们的需求。

收集器接口 Collector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface Collector<T, A, R> {

Supplier<A> supplier();
BiConsumer<A, T> accumulator();
BinaryOperator<A> combiner();
Function<A, R> finisher();
Set<Characteristics> characteristics();
...
enum Characteristics {
CONCURRENT,
UNORDERED,
IDENTITY_FINISH
}
}

可以看出,收集器内部有一个抽象接口需要我们来实现。

阅读全文 »

Stream 虽然已经提供了不少终止操作,但是可能在有些场景下还是无法满足你的使用要求。没关系,如果你发现你想要的终止操作功能接口 Stream 没有提供,不妨试试从 collect 方法查找一下,很大概率上你会有意外收获。

方法定义

<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);

<R, A> R collect(Collector<? super T, A, R> collector);

collect 提供了两个方法,一个是三参数方法,单看参数的话,其实和 reduce 特别像。单参数的方法,需要传入一个收集器。其实点进收集器内部不难发现,Collector 内部定义了三参数方法需要的所有内容。二者的作用都是将流内元素按照一定的要求汇聚成一个最终结果。

1
2
3
4
5
6
7
8
public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
BinaryOperator<A> combiner();
Function<A, R> finisher();
Set<Characteristics> characteristics();
//...省略部分内容
}

collect 方法的返回类型来看,collect 方法的主要作用是将流所有元素汇聚成一个值。从某种意义讲,其实也是 reduce

阅读全文 »

Stream 提供了 reduce 方法,顾名思义,是将流内的元素按照一定的规则汇聚成一个值。

在了解 reduce 之前,我们来先思考一个问题:我们需要哪些内容才能完成汇聚操作?

  1. 数据
  2. 汇聚结果类型
  3. 汇聚方案

而 Stream 本身就是数据源,所以我们只要专注思考我们想要什么类型的返回数据,以及怎么样把数据汇聚起来。

reduce(BinaryOperator)

方法定义

Optional<T> reduce(BinaryOperator<T> accumulator)

这个方法的入参 BinaryOperator,是一个二元操作的函数式接口,也就是提供了数据汇聚的方案。reduce 的过程是分而治之的过程,这个过程不是一步完成的,是元素两两合并,结果再两两合并,直到有最终结果,返回类型为 Optional

其实这部分在 JavaDoc 里用代码解释的很明白,计算得到的初始值用的是取到的第一个元素。整体过程是把流所有的元素合并成一个值,合并的规则是在 accumulator.apply 里定义的。

阅读全文 »

Stream 提供的遍历方法有两个,一个是 foreach,一个是 foreachOrdered。当然,foreach 方法在集合中也存在,相信大家在以前的编码过程中或多或少都有用到过。

方法定义

void forEach(Consumer<? super T> action);
void forEachOrdered(Consumer<? super T> action);

两个方法从使用上来讲都是一样的,具体区别是,在并行流遍历时,由于流元素是多线程在处理,foreach 无法保证处理的顺序,而 foreachOrdered 可以保证处理的顺序。

阅读全文 »