【发布时间】:2014-11-14 16:03:00
【问题描述】:
我正在尝试为 Guava 的 ImmutableList 构建 Java 8 Collector 实现。但我不断收到奇怪的空指针错误。我的收藏家怎么了?
java.lang.NullPointerException 在 java.util.stream.ReferencePipeline.collect(未知来源)在 com.swa.rm.common.test.TestLauncher.main(TestLauncher.java:50)
是我尝试运行此代码时收到的错误...
ImmutableList.of(1,5,2,7,8,2,4) .stream().filter(i -> i % 2 == 0) .collect(新的 ImmutableListCollector()) .forEach(i -> System.out.println(i));
调用这个收集器
package com.swa.rm.common.stream;
import java.util.EnumSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import com.google.common.collect.ImmutableList;
public class ImmutableListCollector<T> implements Collector<T, ImmutableList.Builder<T>, ImmutableList<T>> {
@Override
public Supplier<ImmutableList.Builder<T>> supplier() {
return ImmutableList::builder;
}
@Override
public BiConsumer<ImmutableList.Builder<T>, T> accumulator() {
return (builder, t) -> builder.add(t);
}
@Override
public BinaryOperator<ImmutableList.Builder<T>> combiner() {
return (left, right) -> {
left.addAll(right.build());
return left;
};
}
@Override
public Function<ImmutableList.Builder<T>, ImmutableList<T>> finisher() {
return null;
}
@Override
public Set<Characteristics> characteristics() {
return EnumSet.of(Characteristics.UNORDERED);
}
}
更新:: 这是最终的实现,它现在似乎可以工作了。
import java.util.EnumSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import com.google.common.collect.ImmutableList;
public class ImmutableListCollector<T> implements Collector<T, ImmutableList.Builder<T>, ImmutableList<T>> {
@Override
public Supplier<ImmutableList.Builder<T>> supplier() {
return (() -> ImmutableList.builder());
}
@Override
public BiConsumer<ImmutableList.Builder<T>, T> accumulator() {
return (builder, t) -> builder.add(t);
}
@Override
public BinaryOperator<ImmutableList.Builder<T>> combiner() {
return (left, right) -> {
left.addAll(right.build());
return left;
};
}
@Override
public Function<ImmutableList.Builder<T>, ImmutableList<T>> finisher() {
return (b -> builder.build());
}
@Override
public Set<Characteristics> characteristics() {
return EnumSet.of(Characteristics.UNORDERED);
}
}
【问题讨论】:
-
仅供参考,您的最终实现看起来不正确,因为它的
supplier()返回相同的ImmutableList.Builder实例,而不是每次都创建一个新实例。这样做有多个问题,包括:A)可以同时从多个线程添加构建器,但它不是线程安全的; B)combiner()将把构建器的所有元素添加到构建器本身; C)Collector本身是有状态的,不能重复使用。 -
是的,我确实想通了,我每次都切换供应商以提供一个新的构建器实例,并摆脱了作为财产挂在顶部的那个。我将在今天晚些时候更新上面的代码以反映这一点。
标签: java lambda java-8 guava java-stream