实现Collector接口
为什么要实现Collector接口
有三种方法创建Collector接口
-
Collectors工厂类 -
调用
collect() -
自己实现
Collector接口
理解Collector接口的参数类型
查看接口参数
interface Collector<T, A, R> {
// content of the interface
}
首先检查T和R类型
-
Tstream流中元素类型 -
R通过Collector处理后结果类型
toList()中R为List<T>,toSet()中R为Set<T>。
groupingBy()中R为Map。
A的类型处理非常复杂,如果你使用IDE可能不会显式的提示
example
Collection<String> strings =
List.of("two", "three", "four", "five", "six", "seven", "eight", "nine",
"ten", "eleven", "twelve");
Collector<String, ?, List<String>> listCollector = Collectors.toList();
List<String> list = strings.stream().collect(listCollector);
Collector<String, ?, Set<String>> setCollector = Collectors.toSet();
Set<String> set = strings.stream().collect(setCollector);
Collector<String, ?, Map<Integer, Long>> groupingBy =
Collectors.groupingBy(String::length, Collectors.counting());
Map<Integer, Long> map = strings.stream().collect(groupingBy);
如果自己实现Collector接口,就必须要显式的给出A的类型。A是中间可变的容器类型。例如toList()是ArrayList,toSet()是HashSet。
理解Collector的特征
Collector.Characteristics
有3个特征
-
IDENTITY_FINISH有该特征的不会调用finisher -
UNORDERED不保证处理stream流中元素的顺序性,toSet()有该特征,toList()没有该特征 -
CONCURRENT该特征对并行流特别重要。表示存储stream流中元素的容器(accumulator)支持并发访问。
实现类似toList()和toSet()的Collector
example1
class ToList<T> implements Collector<T, List<T>, List<T>> {
public Supplier<List<T>> supplier() {
return ArrayList::new;
}
public BiConsumer<List<T>, T> accumulator() {
return Collection::add;
}
public BinaryOperator<List<T>> combiner() {
return (list1, list2) -> {list1.addAll(list2); return list1; };
}
public Function<List<T>, List<T>> finisher() {
return Function.identity();
}
public Set<Characteristics> characteristics() {
return Set.of(Characteristics.IDENTITY_FINISH);
}
}
use case
Collection<String> strings =
List.of("one", "two", "three", "four", "five") ;
List<String> result = strings.stream().collect(new ToList<>());
System.out.println("result = " + result);
result
result = [one, two, three, four, five]
example2
class ToSet<T> implements Collector<T, List<T>, List<T>> {
public Supplier<List<T>> supplier() {
return HashSet::new;
}
public BiConsumer<List<T>, T> accumulator() {
return Collection::add;
}
public BinaryOperator<List<T>> combiner() {
return (list1, list2) -> {list1.addAll(list2); return list1; };
}
public Function<List<T>, List<T>> finisher() {
return Function.identity();
}
public Set<Characteristics> characteristics() {
return Set.of(Characteristics.UNORDERED);
}
}
实现类似joining()的Collector
example
class Joining implements Collector<String, StringBuffer, String> {
public Supplier<StringBuffer> supplier() {
return StringBuffer::new;
}
public BiConsumer<StringBuffer, String> accumulator() {
return StringBuffer::append;
}
public BinaryOperator<StringBuffer> combiner() {
return StringBuffer::append;
}
public Function<StringBuffer, String> finisher() {
return Object::toString;
}
public Set<Characteristics> characteristics() {
return Set.of();
}
}
use case
Collection<String> strings =
List.of("one", "two", "three", "four", "five") ;
String result = strings.stream().collect(new Joining());
System.out.println("result = " + result);
result
result = onetwothreefourfive
本文详细探讨了Java中Collector接口的作用,解释了如何通过Collectors工厂类、直接调用collect()方法以及自定义实现来创建Collector。重点介绍了Collector的四个核心方法:supplier、accumulator、combiner和finisher,以及Characteristics特性。通过实例展示了如何实现类似toList()、toSet()和joining()的Collector,并分析了它们的特点和应用场景。

9

被折叠的 条评论
为什么被折叠?



