【问题标题】:Automatically merge several collections to one自动将多个集合合并为一个
【发布时间】:2013-03-28 09:45:37
【问题描述】:

我有一些番石榴Functions,比如Function<String,Set<String>>。使用带有FluentIterable.transform() 的那些会导致FluentIterable<Set<String>>,但是我需要FluentIterable<String>。所以我现在的想法是继承 FluentIterable<E> 并添加一个新方法 transform2() 在返回之前简单地将所有内容合并到一个集合中。

原来的transform方法是这样的:

public final <T> FluentIterable<T> transform(Function<? super E, T> function) {
  return from(Iterables.transform(iterable, function));
}

我为我的子类和transform2() 方法想到了类似的东西:

public abstract class FluentIterable2<E> extends FluentIterable<E> 
{       
    public final <T> FluentIterable<T> transform2(Function<? super E, Collection<T>> function) {
        // (PROBLEM 1) Eclipse complains: The field FluentIterable<E>.iterable is not visible  
        Iterable<Collection<T>> iterables = Iterables.transform(iterable, function);

        // (PROBLEM 2) Collection<T> merged = new Collection<T>(); // I need a container / collection - which one?
        for(Collection<T> iterable : iterables)
        {
            // merged.addAll(iterable);
        }

        // return from(merged);
    }
}

目前我的新子类有两个问题,上面标有PROBLEM 1PROBLEM 2

  • 问题 1:原始 FluentIterable 类中的可迭代字段是私有的 - 我该怎么办?我可以在我的子类中创建一个具有相同名称的新私有字段,这样可以吗?我的子类中调用 super.someMethod() 并使用该字段的方法呢?然后他们会使用可能具有不同值的超类的字段吗?

  • 问题 2:我需要一些通用集合,我可以在其中组合多个集合的内容,但集合是一个接口,所以我无法实例化它。那么,我可以在那里使用哪个类?

如果解决方案仅适用于集合,那将是可以接受的,但我更喜欢适用于集合和列表的解决方案。

感谢您对此的任何提示!

【问题讨论】:

    标签: java generics collections subclass guava


    【解决方案1】:

    FluentIterable.transformAndConcat(stringToSetFunction) 不适用于您的用例吗?

    【讨论】:

    • 这似乎完全符合我的要求,尽管即使现在我还不明白这方面的文档!?
    • 文档的哪一部分你不明白?如果您告诉我们,也许我们可以改进文档。
    • 在我看来,这是抽象的,当我阅读方法名称或 javadoc“返回具有连接结果组合的流畅迭代”时,我想到了连接字符串。好的,现在我注意到,如果您考虑连接 Iterables,它实际上很合适,也许可以添加 sth。像“这意味着函数返回的集合被合并到一个集合”或某事。像那样,但可能这真的只是我的错;-)
    • @LouisWasserman 一个简单的例子通常是物超所值的......尤其是当方法签名充满泛型 Gobbledygook 时。
    【解决方案2】:

    为什么子类 FluentIterable 只是为了做到这一点?你只需要一个简单的循环:

    Set<String> union = Sets.newHashSet();
    for (Set<String> set : fluentIterableOfSets) {
        union.addAll(set);
    }
    

    【讨论】:

    • 好吧,我并不总是想写这个循环,我也想链接几个方法调用(这就是我使用 FluentIterable 的原因),但是我使用的下一个转换函数只需要一个集合,而不是集合的集合。
    【解决方案3】:

    使用FluentIterable.transformAndConcat(f),其中f 是将元素映射到元素类型上的某种可迭代对象的函数。

    在您的情况下,假设您的 Function&lt;String, Set&lt;String&gt;&gt; 称为 TOKENIZE,而您的初始 Iterable&lt;String&gt; 称为 LINES。

    然后要获得一个 Set&lt;String&gt; 来保存 LINES 中的所有不同标记,请执行以下操作:

    Iterable<String> LINES = ...;
    Function<String, Set<String>> TOKENIZE = ...;
    Set<String> TOKENS = FluentIterable.from(LINES)
        .transformAndConcat(TOKENIZE)
        .toSet();
    

    但请仔细考虑 JB Nizet 的回答。尝试两种方式,看看哪种效果更好。

    【讨论】:

    猜你喜欢
    • 2016-11-15
    • 1970-01-01
    • 2011-10-28
    • 2023-03-07
    • 2011-08-06
    • 2019-10-07
    • 2021-03-27
    相关资源
    最近更新 更多