当前位置: 首页 > 知识库问答 >
问题:

如何将 Java 8 流收集到 Guava 不可变集合中?

薛文斌
2023-03-14

我想做以下事情:

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

但在某种程度上,结果列表是Guava的<code>ImmutableList<code>的实现。

我知道我可以做到

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));

但它抛出了一个异常:

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

共有3个答案

邵诚
2023-03-14

虽然不是对我的问题的直接回答(它不使用收藏家),但这是一种相当优雅的方法,不使用中间收藏:

Stream<Integer> stream = IntStream.range(0, 7).boxed();
List<Integer> list = ImmutableList.copyOf(stream.iterator());

来源

万俟亦
2023-03-14

这就是<code>收集器和<code>采集器有用的地方:

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

它将转换应用到您刚刚构建的<code>列表

或者,您可以直接收集到< code>Builder中,并在最后调用< code>build():

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 的静态实用程序方法中定义。这比创建自己的收集器类更简单。

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());
羊舌阎宝
2023-03-14

Alexis的公认答案中的< code>toImmutableList()方法现在包含在Guava 21中,可用作:

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

编辑:从< code > immutablelist . toimmutablelist 中删除了< code>@Beta以及27.1版(6242bdd)中其他常用的API。

 类似资料:
  • 问题内容: 我真的很喜欢Java 8流和Guava的不可变集合,但是我不知道如何将两者一起使用。 例如,如何实现将流结果收集到ImmutableMultimap中的Java 8 Collector? 优点:我希望能够提供键/值映射器,类似于Collectors.toMap()的工作方式。 问题答案: 从21版开始,您可以

  • 问题内容: Java 8中有什么方法可以将一个元素分组而不收集它们?我希望结果再次出现。因为我必须处理大量数据甚至是无限流,所以我无法先收集数据并再次流处理结果。 所有需要分组的元素在第一流中都是连续的。因此,我喜欢使流评估保持懒惰。 问题答案: 无法使用标准Stream API做到这一点。通常,您无法执行此操作,因为将来总是有可能出现属于任何已创建组的新项目,因此,在处理所有输入之前,您无法将组

  • 在Java8中有什么方法可以在中分组元素而不收集它们吗?我希望结果再次成为。因为我必须处理大量的数据,甚至是无限的流,所以我不能首先收集数据,然后再次流化结果。 所有需要分组的元素在第一个流中是连续的。因此,我喜欢保持流评估懒惰。

  • 我有一个HashMap,我需要使用一些函数对其进行筛选: 上述代码中的错误是变量的声明类型。应该是而不是。 所以现在的功能代码是:

  • 我想将流放入不可变列表中。从性能的角度来看,以下方法与哪种方法更好有什么区别? > <code>collect(Collectors.collectingAndThen(collector.toList(),ImmutableList::copyOf))

  • 问题内容: 从Java 1.6 Collection Framework文档中 : 不支持任何修改操作(如类别,和)被称为 不可修改的 。[…]额外保证Collection对象中的任何更改都将不可见的Collection被称为 不可变的 。 第二个标准使我有些困惑。鉴于第一个集合是不可修改的,并且假定原始集合引用已被删除,那么第二行中提到的更改是什么?它是指集合中包含的元素的变化,即元素的状态吗?