【问题标题】:Flattening an Iterable<Iterable<T>> in Guava在 Guava 中展平一个 Iterable<Iterable<T>>
【发布时间】:2011-08-22 09:19:32
【问题描述】:

Guava 中是否有 flatten 方法 - 或将 Iterable&lt;Iterable&lt;T&gt;&gt; 转换为 Iterable&lt;T&gt; 的简单方法?

我有一个Multimap&lt;K, V&gt; [sourceMultimap],我想返回键匹配某个谓词 [keyPredicate] 的所有值。所以目前我有:

Iterable<Collection<V>> vals = Maps.filterKeys(sourceMultimap.asMap(), keyPredicate).values();

Collection<V> retColl = ...;
for (Collection<V> vs : vals) retColl.addAll(vs);
return retColl;

我浏览了 Guava 文档,但没有任何内容。我只是在检查我没有错过任何东西。否则,我会将我的三行代码提取到一个简短的 flatten 泛型方法中并保持不变。

【问题讨论】:

    标签: java collections guava flatten


    【解决方案1】:

    Iterables.concat method 满足该要求:

    public static <T> Iterable<T> concat(Iterable<? extends Iterable<? extends T>> inputs)
    

    【讨论】:

    【解决方案2】:

    从 Java 8 开始,您可以在没有 Guava 的情况下执行此操作。这有点笨拙,因为Iterable doesn't directly provide streams,需要使用 StreamSupport,但它不需要像问题中的代码那样创建新集合。

    private static <T> Iterable<T> concat(Iterable<? extends Iterable<T>> foo) {
        return () -> StreamSupport.stream(foo.spliterator(), false)
            .flatMap(i -> StreamSupport.stream(i.spliterator(), false))
            .iterator();
    }
    

    【讨论】:

    • 不适合我的需要,因为我的迭代器是惰性的,但是当将这样的迭代器转换为流时,所有的惰性都会丢失。
    • @odiszapc 我不确定你的意思。 Iterable.spliterator() 只返回一个 Spliterator 包装 Iterable.iterator();在流的终端操作开始之前不会绘制任何元素。同样,StreamSupport.stream 明确记录在终端操作开始之前不要开始查询拆分器。所以我认为你是说你的顶级 iterable 是懒惰的,你想延迟调用 iterator() 吗?在这种情况下,使用 StreamSupport.stream 重载获取供应商 (StreamSupport.stream(() -&gt; foo.spliterator(), false))。
    • @odiszapc 否则,如果您有时间做一个,我会对重现此答案为何不起作用的最小示例感兴趣,因为我会从中学到一些东西。
    猜你喜欢
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-06
    • 2013-07-31
    • 2017-08-25
    • 2019-11-07
    相关资源
    最近更新 更多