协调的协变集合

时间:2012-09-26 05:30:39

标签: java generics collections

我的(蒸馏)场景:

假设我有一个名为Interfaceclass Foo implements Interface的界面。

我还有一个通用的可迭代“结果”类,除其他外,它委托给一个集合来做可迭代的东西。 Result类会执行与问题无关的其他内容。所以:

class Result<E> implements Iterable<E> {

    private Collection<E> delegate;

    public Result(Collection<E> delegate) {
        this.delegate = delegate;
    }

    public Iterator<E> iterator() {
        return delegate.iterator();
    }

    // ... other irrelevant stuff.
}

传递到Result的集合可能很大,而Result对象的用户可能会在几个元素之后停止迭代(但我无法控制多少元素)。

然后,我有另一个类,我们称之为Query,它在内部拥有Foo的集合,但需要能够返回Result。它目前看起来像这样:

class Query {
    private Collection<Foo> data;

    public Result<Interface> getAllData() {
        return new Result<Interface>(new ArrayList<Interface>(data));
    }

    // EDIT: Not all Result objects are of Interfaces.
    public Result<SomeUnrelatedInterface> getSomeOtherData() {
        return ...;
    }
}

因此getAllData会获取数据的副本(作为ArrayList<Interface>),并将其传递给新的Result进行委派。这对我来说并不理想,因为那个集合可能很庞大,结果的接收者可能只需要前几个结果。

现在提出问题:

任何人都可以想到改变事物的方式,这样我就不需要拍摄具体集合的副本吗?

理想情况下,我希望Result的构造函数为public Result(Collection<? extends E> delegate)(与大多数Collection一样),并以某种方式使该集合适应Collection<E>,但是我无法弄清楚那可能是什么样的。

2 个答案:

答案 0 :(得分:3)

您可以使用以下变体吗?

class Result<E extends Interface>
 implements Iterable<E> {

    private Collection<E> delegate;

    public Result(Collection<E> delegate) {
        this.delegate = delegate;
    }
    public Iterator<E> iterator() {
        return delegate.iterator();
    }
}
class Query {
    private Collection<Foo> data;

    public Result<? extends Interface> getAllData() {
        return new Result<Foo>(data);
    }
}

答案 1 :(得分:1)

如您所知,将Collection<? extends E>变为Collection<E>的危险在于,现在调用者可以将任何E放入其中。所以你必须排除这一点,你会没事的。 Collections.unmodifiableCollection(Collection)就是这样做的,它甚至会将结果显示为Collection<E>

修改

Collection<? extends Interface> foos = new ArrayList<Foo>();
Collection<Interface> adapted = Collections.unmodifiableCollection(foos);