不需要将函数实现为容器类的方法。
这就是这种总和收集器的典型实现方式
public static Collector<Integer, ?, Integer> sum() {
return Collector.of(() -> new int[1],
(a, i) -> a[0] += i,
(a, b) -> { a[0] += b[0]; return a; },
a -> a[0],
Collector.Characteristics.UNORDERED);
}
但是,当然,您也可以将其实现为
public static Collector<Integer, ?, Integer> sum() {
return Collector.of(AtomicInteger::new,
AtomicInteger::addAndGet,
(a, b) -> { a.addAndGet(b.intValue()); return a; },
AtomicInteger::intValue,
Collector.Characteristics.UNORDERED, Collector.Characteristics.CONCURRENT);
}
您首先必须为您的收集器找到合适的可变容器类型。如果不存在这样的类型,则必须创建自己的类。这些函数可以实现为对现有方法的方法引用或 lambda 表达式。
对于更复杂的例子,我不知道是否有合适的现有类型来容纳int
and a List
,但你可能会用盒装的Integer
, 像这样
final Map<String, Integer> map = …
List<String> keys = map.entrySet().stream().collect(keysToMaximum());
public static <K> Collector<Map.Entry<K,Integer>, ?, List<K>> keysToMaximum() {
return Collector.of(
() -> new AbstractMap.SimpleEntry<>(new ArrayList<K>(), Integer.MIN_VALUE),
(current, next) -> {
int max = current.getValue(), value = next.getValue();
if(value >= max) {
if(value > max) {
current.setValue(value);
current.getKey().clear();
}
current.getKey().add(next.getKey());
}
}, (a, b) -> {
int maxA = a.getValue(), maxB = b.getValue();
if(maxA <= maxB) return b;
if(maxA == maxB) a.getKey().addAll(b.getKey());
return a;
},
Map.Entry::getKey
);
}
但是您也可以创建一个新的专用容器类作为临时类型,在特定收集器之外不可见
public static <K> Collector<Map.Entry<K,Integer>, ?, List<K>> keysToMaximum() {
return Collector.of(() -> new Object() {
int max = Integer.MIN_VALUE;
final List<K> keys = new ArrayList<>();
}, (current, next) -> {
int value = next.getValue();
if(value >= current.max) {
if(value > current.max) {
current.max = value;
current.keys.clear();
}
current.keys.add(next.getKey());
}
}, (a, b) -> {
if(a.max <= b.max) return b;
if(a.max == b.max) a.keys.addAll(b.keys);
return a;
},
a -> a.keys);
}
要点是,您不需要创建一个新的命名类来创建Collector
.