如何将流结果存储到多个列表或映射中

时间:2017-04-30 03:05:22

标签: java java-8 java-stream

有没有更好的方法呢?请注意以下代码正常运作。

List<Object1> details1 = new ArrayList<>();
List<Object2> details2 = new ArrayList<>();
List<Object3> details3 = new ArrayList<>();    
endPointList.parallelStream().forEach(endPoint -> {
details1.addAll(ConfigHelper.getConfig1(endPoint));
details2.addAll(ConfigHelper.getConfig2(endPoint));
details3.addAll(ConfigHelper.getConfig3(endPoint));
});

1 个答案:

答案 0 :(得分:1)

我认为没有内置的方法可以做到这一点。但是如果你必须经常这样做,那么编写你自己的Collector可能是值得的。这不会缩短,但在使用时看起来会更像其他收藏家。

public static class ConfigCollector implements Collector<EndPoint, ConfigCollector, ConfigCollector>
{
    List<Config1> config1s = new CopyOnWriteArrayList<>();
    List<Config2> config2s = new CopyOnWriteArrayList<>();
    List<Config3> config3s = new CopyOnWriteArrayList<>();

    public List<Config1> getConfig1s() { return config1s; }
    public List<Config2> getConfig2s() { return config2s; }
    public List<Config3> getConfig3s() { return config3s; }

    @Override
    public BiConsumer<ConfigCollector, EndPoint> accumulator()
    {
        return (cc, e) -> {
            cc.config1s.addAll(ConfigHelper.getConfig1(endPoint));
            cc.config2s.addAll(ConfigHelper.getConfig2(endPoint));
            cc.config3s.addAll(ConfigHelper.getConfig3(endPoint));
        };
    }

    @Override
    public Set<java.util.stream.Collector.Characteristics> characteristics()
    {
        HashSet<java.util.stream.Collector.Characteristics> set = new HashSet<>();
        set.add(Characteristics.IDENTITY_FINISH);
        set.add(Characteristics.UNORDERED);
        set.add(Characteristics.CONCURRENT);
        return set;
    }

    @Override
    public BinaryOperator<ConfigCollector> combiner()
    {
        return (cc1, cc2) -> {
            cc1.config1s.addAll(cc2.config1s);
            cc1.config2s.addAll(cc2.config2s);
            cc1.config3s.addAll(cc2.config3s);
            return cc1;
        };
    }

    @Override
    public Function<ConfigCollector, ConfigCollector> finisher()
    {
        return Function.identity();
    }

    @Override
    public Supplier<ConfigCollector> supplier()
    {
        return ConfigCollector::new;
    }
}

像这样使用它:

ConfigCollector configs = endPointList.parallelStream().collect(new ConfigCollector());
configs.getConfig1s();
configs.getConfig2s();
configs.getConfig3s();

这样可以更轻松地处理其他评论者提到的有关并发的内容(当您在收集器内而不是在业务代码内部处理它时)。也许你没有遇到这个问题,因为你的流足够小,所以它还没有在paralllel做任何事情。