【问题标题】:A collection that represents a concatenation of two collections in Java表示 Java 中两个集合的串联的集合
【发布时间】:2009-11-15 16:50:15
【问题描述】:

是否有一个类表示一个集合与另一个集合的连接?这个类本身应该是一个集合,并且应该将所有方法委托给底层(内部)集合 - 不应分配额外的内存,也不应修改任何原始集合。

示例用法:

Collection<String> foo = ...
Collection<String> bar = ...

// this should be O(1) memory and time
Collection<String> combined = concat(foo, bar);

if (combined.contains("Zee"))
  ...

for (String str : combined)
  System.out.println(str);

【问题讨论】:

  • 你的意思是类似于 Python 的 itertools 提供的东西?
  • 不清楚你是否想要一个代表一个集合和一个项目、两个集合或什么的类..
  • 表示两个集合串联的类。
  • 如果add() 被调用在连接的集合上会发生什么? remove() 怎么样?
  • 您可能想在您的问题中进行澄清,以帮助他人。但是,您有带有定义的英语词典和带有定义的德语词典,并且您希望它们在同一个集合中,但是您希望能够访问所有三个集合,因此前两个没有被修改,并且您不想在这个新的第三个集合中使用任何额外的内存?这是一个正确的场景吗?

标签: java data-structures collections


【解决方案1】:

与任何收藏品一样,请查看google-collections。如果你有Sets,特别是(不仅仅是一般集合),你想要:

Set<String> combined = Sets.union(foo, bar);

这会创建两个集合的不可修改视图。也就是说,foobar 的更改将反映在 combined 中(但不支持 combined.add() 等)。

对于更通用的情况,您有Iterables.concat(),但这只是让您可以迭代连接的项目,Iterable 接口显然不包括contains,所以您有点担心。

google-collections 中的其他集合实用程序类(com.google.common.collect.Listscom.google.common.collect.Collections2)不包含任何连接方法。不明白为什么他们不能,但目前他们不能。

【讨论】:

  • 我们发现在 99% 的情况下,用户真的只需要迭代。因此 Iterables.concat()。在内部,我们也有一个 Lists.concat(),但几乎没有人使用它,而且大多数使用它的人无论如何都可以使用另一个。
【解决方案2】:

你的问题很模糊。尤其是“with another item another collection”是很不清楚的。

您至少可以使用Collection#addAll() 将另一个Collection 的内容添加到当前Collection。这里Collection 可以是它的任何子接口/实现,例如ListSet

例子:

List<String> foos = Arrays.asList("foo1", "foo2", "foo3");
List<String> bars = Arrays.asList("bar1", "bar2", "bar3");
foos.addAll(bars); // Now foos contains everything.

编辑:或者你真的想在现有Collection 的基础上创建一个 Collection,然后向其中添加一个新项目?在这种情况下,只需使用现有的Collection 作为构造函数参数构造一个新的Collection。例如:

List<String> foos = Arrays.asList("foo1", "foo2", "foo3");
List<String> bars = new ArrayList<String>(foos);
bars.add("bar"); // Now bars contains everything.

【讨论】:

  • 在使用第三方库之前,我总是更喜欢原生 Java 库的方式来做事。
【解决方案3】:

没有,但自己写应该是直截了当的

package ch.akuhn.util;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class Concat {

    public static <T> Iterable<T> all(final Iterable<T>... iterables) {
        return new Iterable<T>() {
            @Override
            public Iterator<T> iterator() {
                return new Iterator<T>() {
                    Iterator<Iterable<T>> more = Arrays.asList(iterables).iterator();
                    Iterator<T> current = more.hasNext() ? more.next().iterator() : null;
                    @Override
                    public boolean hasNext() {
                        if (current == null) return false;
                        if (current.hasNext()) return true;
                        current = more.hasNext() ? more.next().iterator() : null;
                        return this.hasNext();
                    }

                    @Override
                    public T next() {
                        if (!hasNext()) throw new NoSuchElementException();
                        return current.next();
                    }

                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

}

然后

for (Object each: Concat.all(collection,whatever,etcetera,...)) {
    // ...
}

只是在这里写了这段代码,编译风险自负!

PS,如果你要为这个类编写单元测试,请将它们发送给我。

【讨论】:

    【解决方案4】:

    我认为您需要的是一种 Java 构造,它允许您将集合放在一起而无需修改原始集合。换句话说,您有集合 A 和 B,大小分别为 N 和 M。在 concat 调用之后,您仍然有集合 A 和 B,它们的大小仍然是 N 和 M,但是您还有集合 C,它指向 A 和 B,使其大小为 N+M。

    答案是否定的,Java 没有任何开箱即用的功能...但是您可以编写一个快速包装器来包装一系列集合并将这些集合添加到其中。 (它所要做的就是维护对每个集合的引用)并且您可以根据需要公开 get/insert 方法。

    【讨论】:

    • 这确实是我要找的……想知道是否有这样的图书馆。
    【解决方案5】:

    Apache Commons Collections 还有一个更通用的CompositeCollection 类,它可以用作任意数量的Collections 的接口。

    【讨论】:

      【解决方案6】:

      我不确定你在问什么。我对您的问题的解释是您在 Collection 上寻找 add 方法。不过,我认为这不是您要问的。

      【讨论】:

      • 我正在寻找一个封装两个集合串联的集合, 不会分配大量内存或修改原始集合。
      【解决方案7】:

      试试 InterleavingEnumeration 或 apache 的公共集合的 ListUtils (ListUtils.union())

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-13
        相关资源
        最近更新 更多