将多个集合组合成一个逻辑集合? [英] Combine multiple Collections into a single logical Collection?

查看:25
本文介绍了将多个集合组合成一个逻辑集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设,我有固定数量的集合(例如 3 个 ArrayLists)作为类的成员.现在,我想将所有元素公开给其他类,以便他们可以简单地迭代所有元素(理想情况下,只读).我正在使用番石榴集合,我想知道如何使用番石榴迭代器/迭代器来生成内部集合的逻辑视图制作临时副本.

解决方案

有了 Guava,你可以使用 Iterables.concat(Iterable ...),它创建所有可迭代对象的实时视图,连接为一个(如果您更改可迭代对象,则连接的版本也会更改).然后用 Iterables.unmodifiableIterable(Iterable)(我之前没有看到只读要求).

来自 Iterables.concat( .. ) JavaDocs:

<块引用>

将多个可迭代对象组合成一个单个可迭代.返回的可迭代对象有一个迭代器遍历输入中每个可迭代的元素.不轮询输入迭代器直到必要.返回的iterable 的迭代器支持 remove()当对应的输入迭代器支持.

虽然这并没有明确说明这是一个实时视图,但最后一句暗示它是(支持 Iterator.remove() 方法仅当支持迭代器支持时才可行,除非使用实时视图)>

示例代码:

final Listfirst = Lists.newArrayList(1, 2, 3);最终列表<整数>第二个 = Lists.newArrayList(4, 5, 6);最终列表<整数>第三 = Lists.newArrayList(7, 8, 9);final Iterable全部 =Iterables.unmodifiableIterable(Iterables.concat(第一、第二、第三));System.out.println(all);第三.add(9999999);System.out.println(all);

输出:

<块引用>

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9999999]

<小时>

根据 Damian 的请求,这里有一个类似的方法返回一个实时的集合视图

public final class CollectionsX {静态类 JoinedCollectionView实现 Collection{私人最终收藏[] 项;public JoinedCollectionView(final Collection[] items) {this.items = 物品;}@覆盖public boolean addAll(final Collection c) {抛出新的 UnsupportedOperationException();}@覆盖公共无效清除(){for (final Collection coll : items) {coll.clear();}}@覆盖公共布尔包含(最终对象 o){抛出新的 UnsupportedOperationException();}@覆盖public boolean containsAll(final Collection<?> c) {抛出新的 UnsupportedOperationException();}@覆盖公共布尔 isEmpty() {返回 !iterator().hasNext();}@覆盖公共迭代器<E>迭代器(){返回 Iterables.concat(items).iterator();}@覆盖公共布尔删除(最终对象 o){抛出新的 UnsupportedOperationException();}@覆盖public boolean removeAll(final Collection<?>c){抛出新的 UnsupportedOperationException();}@覆盖公共布尔保留所有(最终集合 c){抛出新的 UnsupportedOperationException();}@覆盖公共整数大小(){int ct = 0;for (final Collection coll : items) {ct += coll.size();}返回 ct;}@覆盖公共对象[] toArray() {抛出新的 UnsupportedOperationException();}@覆盖公共 <T>T[] toArray(T[] a) {抛出新的 UnsupportedOperationException();}@覆盖公共布尔添加(E e){抛出新的 UnsupportedOperationException();}}/*** 返回传入集合的实时聚合集合视图.* <p>* 除 {@link Collection#size()}、{@link Collection#clear()} 之外的所有方法,* {@link Collection#isEmpty()} 和 {@link Iterable#iterator()}* 在返回的集合中抛出 {@link UnsupportedOperationException}.* <p>* 以上方法都不是线程安全的(也没有简单的方法*制作它们).*/公共静态<T>集合<T>结合(最终集合... 项目) {返回新的 JoinedCollectionView(items);}私人收藏X(){}}

Assume, I have a constant number of collections (e.g. 3 ArrayLists) as members of a class. Now, I want to expose all the elements to other classes so they can simply iterate over all elements (ideally, read only). I'm using guava collections and I wonder how I could use guava iterables/iterators to generate a logical view on the internal collections without making temporary copies.

解决方案

With Guava, you can use Iterables.concat(Iterable<T> ...), it creates a live view of all the iterables, concatenated into one (if you change the iterables, the concatenated version also changes). Then wrap the concatenated iterable with Iterables.unmodifiableIterable(Iterable<T>) (I hadn't seen the read-only requirement earlier).

From the Iterables.concat( .. ) JavaDocs:

Combines multiple iterables into a single iterable. The returned iterable has an iterator that traverses the elements of each iterable in inputs. The input iterators are not polled until necessary. The returned iterable's iterator supports remove() when the corresponding input iterator supports it.

While this doesn't explicitly say that this is a live view, the last sentence implies that it is (supporting the Iterator.remove() method only if the backing iterator supports it is not possible unless using a live view)

Sample Code:

final List<Integer> first  = Lists.newArrayList(1, 2, 3);
final List<Integer> second = Lists.newArrayList(4, 5, 6);
final List<Integer> third  = Lists.newArrayList(7, 8, 9);
final Iterable<Integer> all =
    Iterables.unmodifiableIterable(
        Iterables.concat(first, second, third));
System.out.println(all);
third.add(9999999);
System.out.println(all);

Output:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9999999]


Edit:

By Request from Damian, here's a similar method that returns a live Collection View

public final class CollectionsX {

    static class JoinedCollectionView<E> implements Collection<E> {

        private final Collection<? extends E>[] items;

        public JoinedCollectionView(final Collection<? extends E>[] items) {
            this.items = items;
        }

        @Override
        public boolean addAll(final Collection<? extends E> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void clear() {
            for (final Collection<? extends E> coll : items) {
                coll.clear();
            }
        }

        @Override
        public boolean contains(final Object o) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean containsAll(final Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean isEmpty() {
            return !iterator().hasNext();
        }

        @Override
        public Iterator<E> iterator() {
            return Iterables.concat(items).iterator();
        }

        @Override
        public boolean remove(final Object o) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean removeAll(final Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean retainAll(final Collection<?> c) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int size() {
            int ct = 0;
            for (final Collection<? extends E> coll : items) {
                ct += coll.size();
            }
            return ct;
        }

        @Override
        public Object[] toArray() {
            throw new UnsupportedOperationException();
        }

        @Override
        public <T> T[] toArray(T[] a) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean add(E e) {
            throw new UnsupportedOperationException();
        }

    }

    /**
     * Returns a live aggregated collection view of the collections passed in.
     * <p>
     * All methods except {@link Collection#size()}, {@link Collection#clear()},
     * {@link Collection#isEmpty()} and {@link Iterable#iterator()}
     *  throw {@link UnsupportedOperationException} in the returned Collection.
     * <p>
     * None of the above methods is thread safe (nor would there be an easy way
     * of making them).
     */
    public static <T> Collection<T> combine(
        final Collection<? extends T>... items) {
        return new JoinedCollectionView<T>(items);
    }

    private CollectionsX() {
    }

}

这篇关于将多个集合组合成一个逻辑集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆