为了账号安全,请及时绑定邮箱和手机立即绑定

将多个集合合并为一个逻辑集合?

将多个集合合并为一个逻辑集合?

大话西游666 2019-12-25 15:35:23
假设我有恒定数量的集合(例如3个ArrayList)作为类的成员。现在,我想将所有元素公开给其他类,以便它们可以简单地遍历所有元素(理想情况下为只读)。我正在使用番石榴集合,不知道如何使用番石榴可迭代器/迭代器在内部集合上生成逻辑视图而无需制作临时副本。
查看完整描述

3 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

使用Guava,您可以使用Iterables.concat(Iterable<T> ...),它创建所有可迭代对象的实时视图,并串联在一起(如果更改可迭代对象,则串联版本也会更改)。然后将串联的可迭代对象包装为Iterables.unmodifiableIterable(Iterable<T>)(我之前没有看到只读要求)。


从Iterables.concat( .. )JavaDocs:


将多个可迭代项合并为一个可迭代项。返回的Iterable具有迭代器,该迭代器遍历输入中每个Iterable的元素。直到必要时才轮询输入迭代器。remove() 当相应的输入迭代器支持它时,返回的iterable的迭代器也将支持它。


虽然这并未明确表示这是实时视图,但最后一句话暗示它是(Iterator.remove()仅在支持后备迭代器支持的情况下才支持该方法,除非使用实时视图)


样例代码:


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);

输出:


[1、2、3、4、5、6、7、8、9]

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


编辑:


根据Damian的要求,这是一种类似的方法,可返回实时的“收藏夹视图”


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() {

    }


}


查看完整回答
反对 回复 2019-12-25
?
慕工程0101907

TA贡献1887条经验 获得超5个赞

使用Java的纯Java 8解决方案Stream。


常数

假设private Collection<T> c, c2, c3。


一种解决方案:


public Stream<T> stream() {

    return Stream.concat(Stream.concat(c.stream(), c2.stream()), c3.stream());

}

另一个解决方案:


public Stream<T> stream() {

    return Stream.of(c, c2, c3).flatMap(Collection::stream);

}

可变数

假设private Collection<Collection<T>> cs:


public Stream<T> stream() {

    return cs.stream().flatMap(Collection::stream);

}


查看完整回答
反对 回复 2019-12-25
?
catspeake

TA贡献1111条经验 获得超0个赞

如果您至少使用Java 8,请参阅我的其他答案。


如果您已经在使用Google Guava,请参见Sean Patrick Floyd的答案。


如果您坚持使用Java 7,并且不想包含Google Guava,则可以Iterables.concat()使用Iterable和最多编写自己的(只读)代码Iterator:


常数

public static <E> Iterable<E> concat(final Iterable<? extends E> iterable1,

                                     final Iterable<? extends E> iterable2) {

    return new Iterable<E>() {

        @Override

        public Iterator<E> iterator() {

            return new Iterator<E>() {

                final Iterator<? extends E> iterator1 = iterable1.iterator();

                final Iterator<? extends E> iterator2 = iterable2.iterator();


                @Override

                public boolean hasNext() {

                    return iterator1.hasNext() || iterator2.hasNext();

                }


                @Override

                public E next() {

                    return iterator1.hasNext() ? iterator1.next() : iterator2.next();

                }

            };

        }

    };

}

可变数

@SafeVarargs

public static <E> Iterable<E> concat(final Iterable<? extends E>... iterables) {

    return concat(Arrays.asList(iterables));

}


public static <E> Iterable<E> concat(final Iterable<Iterable<? extends E>> iterables) {

    return new Iterable<E>() {

        final Iterator<Iterable<? extends E>> iterablesIterator = iterables.iterator();


        @Override

        public Iterator<E> iterator() {

            return !iterablesIterator.hasNext() ? Collections.emptyIterator()

                                                : new Iterator<E>() {

                Iterator<? extends E> iterableIterator = nextIterator();


                @Override

                public boolean hasNext() {

                    return iterableIterator.hasNext();

                }


                @Override

                public E next() {

                    final E next = iterableIterator.next();

                    findNext();

                    return next;

                }


                Iterator<? extends E> nextIterator() {

                    return iterablesIterator.next().iterator();

                }


                Iterator<E> findNext() {

                    while (!iterableIterator.hasNext()) {

                        if (!iterablesIterator.hasNext()) {

                            break;

                        }

                        iterableIterator = nextIterator();

                    }

                    return this;

                }

            }.findNext();

        }

    };

}


查看完整回答
反对 回复 2019-12-25
  • 3 回答
  • 0 关注
  • 680 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信