我如何将Java 8流收集到Guava ImmutableCollection中?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (7)

我想要做以下事情:

List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());

但结果列表是实施番石榴的方式ImmutableList

我知道我能做到

List<Integer> list = IntStream.range(0, 7).collect(Collectors.toList());
List<Integer> immutableList = ImmutableList.copyOf(list);

但我想直接收集。我试过了

List<Integer> list = IntStream.range(0, 7)
    .collect(Collectors.toCollection(ImmutableList::of));

但它抛出了一个例外:

com.google.common.collect.ImmutableCollection.add(ImmutableCollection.java:96)上的java.lang.UnsupportedOperationException

提问于
用户回答回答于

这是collectingAndThen收集器有用的地方:

List<Integer> list = IntStream.range(0, 7).boxed()
                .collect(collectingAndThen(toList(), ImmutableList::copyOf));

它将转换应用于List刚建立的你; 导致一个ImmutableList

或者你可以直接收集Builderbuild()在最后通话:

List<Integer> list = IntStream.range(0, 7)
                .collect(Builder<Integer>::new, Builder<Integer>::add, (builder1, builder2) -> builder1.addAll(builder2.build()))
                .build();

如果这个选项对你来说有点冗长,并且你想在很多地方使用它,你可以创建你自己的收集器:

class ImmutableListCollector<T> implements Collector<T, Builder<T>, ImmutableList<T>> {
    @Override
    public Supplier<Builder<T>> supplier() {
        return Builder::new;
    }

    @Override
    public BiConsumer<Builder<T>, T> accumulator() {
        return (b, e) -> b.add(e);
    }

    @Override
    public BinaryOperator<Builder<T>> combiner() {
        return (b1, b2) -> b1.addAll(b2.build());
    }

    @Override
    public Function<Builder<T>, ImmutableList<T>> finisher() {
        return Builder::build;
    }

    @Override
    public Set<Characteristics> characteristics() {
        return ImmutableSet.of();
    }
}

接着:

List<Integer> list = IntStream.range(0, 7)
                              .boxed()
                              .collect(new ImmutableListCollector<>());

以防链接在评论中消失; 我的第二种方法可以在一个简单使用的静态实用程序方法中定义Collector.of。这比创建自己的Collector班级更简单。

public static <T> Collector<T, Builder<T>, ImmutableList<T>> toImmutableList() {
    return Collector.of(Builder<T>::new, Builder<T>::add, (l, r) -> l.addAll(r.build()), Builder<T>::build);
}

和用法:

 List<Integer> list = IntStream.range(0, 7)
                               .boxed()
                               .collect(toImmutableList());
用户回答回答于

toImmutableList()Alexis接受的答案中的方法现在包含在 Guava 21中,可用作:

ImmutableList<Integer> list = IntStream.range(0, 7).boxed().collect(ImmutableList.toImmutableList());

扫码关注云+社区