目标
完成一个简单的MyListCollector
,能将对应的Stream
转换为List
Collector是什么?
举个具体的例子:
list.stream().filter(x -> x > 2).collect(new MyListCollector());
我们想要将一个list
中大于2的所有元素都筛选出来,首先list
转化为stream
,对每一个元素进行判断。但是判断完以后,我们如何将stream
转换为我们想要的类型呢?这时候可以使用collect()
方法,collect()
方法需要的参数就是一个Collector
,这个Collector
告诉了collect
方法,如何去将这个stream
转换为我们想要的对象。
Collector接口
collect
方法接收的Collector
,都必须实现Collector
接口,我们简单的看一下Collector
接口:
- 先来看一下泛型
T
:Collector
需要操作的对象,也就是传进来的参数;A
:中间容器,操作过程中存储T
的容器;R
:返回的结果。
- 看一下接口方法
public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
BinaryOperator<A> combiner();
Function<A, R> finisher();
Set<Characteristics> characteristics();
}
Collector
接口需要我们实现的一共五个,前4个定义了如何将传进来的数据进行处理,返回。最后一个方法定义了是否允许使用多线程处理,如何优化处理过程。
Supplier<A> supplier()
:提供一个容器,即接口泛型的A
,所以返回类型Supplier<A>
的泛型(返回类型)为A
。所以我们的接口此方法实现为:
public Supplier<List<E>> supplier() {
return ArrayList::new;
}
BiConsumer<A, T> accumulator()
:这个方法定义了如何处理传入的参数。T
为传入的参数,A
为容器,也就是说,如何将传入的参数(A
)放到容器(T
)里。我们的接口,此方法实现为:
public BiConsumer<List<E>, E> accumulator {
return List::add;
}
Function<A, R> finisher()
:我们刚刚已经提到了,A
只是作为一个中间容器,R
才是最终的返回值。这个方法,就是用于定义如何将容器转换为最终结果的。所以我们的接口此方法的实现为:
public Function<List<E>, List<E>> finisher() {
return Function.identity();
}
BinaryOperator<A> combiner()
:此方法用于,当Stream
被分割为多个的时候,如何将多个中间容器结合在一起。
public BinaryOperator<A> combiner() {
return (l1, l2) -> {
l1.addAll(l2);
return l1;
}
}
Set<Characteristics> characteristics()
:这个方法返回一个Set<Characteristics>
,Characteristics
是一个枚举类,一共有三个取值:
– UNORDERED:返回的结果是无序的;
– CONCURRENT:该Collector
可以在多线程环境下使用,如果此Collector
不是UNORDERED,那么这个Collector
只有传入的数据是无序的时候,才能在多线程环境下使用;
– IDENTITY_FINISH:中间容器和返回值的类型一致。A
转换为R
的时候,不需要检查。
MyListCollector
结合以上,我们的接口实现为:
public class MyListCollector<E> implements Collector<E, List<E>, List<E>>{
@Override
public Supplier<List<E>> supplier() {
return ArrayList::new;
}
@Override
public BiConsumer<List<E>, E> accumulator() {
return List::add;
}
@Override
public BinaryOperator<List<E>> combiner() {
return (list1, list2) -> {
list1.addAll(list2);
return list1;
};
}
@Override
public Function<List<E>, List<E>> finisher() {
return Function.identity();
}
@Override
public Set<Characteristics> characteristics() {
return null;
}
}
参考:Java 8 in action