Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将多个集合合并到单个逻辑集合中?_Java_Collections_Guava - Fatal编程技术网

Java 将多个集合合并到单个逻辑集合中?

Java 将多个集合合并到单个逻辑集合中?,java,collections,guava,Java,Collections,Guava,假设,我有一个固定数量的集合(例如3个ArrayList)作为一个类的成员。现在,我想将所有元素公开给其他类,这样它们就可以简单地迭代所有元素(理想情况下为只读)。 我使用的是guava collections,我想知道如何使用guava iterables/迭代器来生成内部集合的逻辑视图,而无需制作临时副本。您可以创建一个新的列表和添加其他列表。然后返回一个包含集合的不可修改列表。不可修改列表()对于番石榴,您可以使用,它创建一个连接到一个集合的所有iterables的实时视图(如果更改ite

假设,我有一个固定数量的集合(例如3个ArrayList)作为一个类的成员。现在,我想将所有元素公开给其他类,这样它们就可以简单地迭代所有元素(理想情况下为只读)。
我使用的是guava collections,我想知道如何使用guava iterables/迭代器来生成内部集合的逻辑视图,而无需制作临时副本。

您可以创建一个新的
列表
添加其他
列表
。然后返回一个包含集合的不可修改列表。不可修改列表()

对于番石榴,您可以使用,它创建一个连接到一个集合的所有iterables的实时视图(如果更改iterables,连接的版本也会更改)。然后将连接的iterable包装为(我之前没有看到只读要求)

从JavaDocs:

将多个ITerable组合成一个 单一的可复制的。返回的数据是不可接受的 有一个遍历 输入中每个iterable的元素。 未轮询输入迭代器 直到有必要为止。返回 iterable的迭代器支持
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);
final List first=Lists.newArrayList(1,2,3);
final List second=Lists.newArrayList(4,5,6);
最终列表第三个=Lists.newArrayList(7,8,9);
最后一项=
不可修改的(
第一,第二,第三);
系统输出打印项次(全部);
第三,增加(9999999);
系统输出打印项次(全部);
输出:

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,999999]


编辑:

根据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() {
    }

}
公共最终类集合X{
静态类JoinedCollectionView实现收集{

私有最终集合使用

常数 假设
私有集合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);
}
publicstream(){
返回Stream.concat(Stream.concat(c.Stream()、c2.Stream()、c3.Stream());
}
另一个解决方案:

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);
}
publicstream(){
返回流.of(c,c2,c3).flatMap(集合::流);
}
可变数 假设私人收藏cs

public Stream<T> stream() {
    return cs.stream().flatMap(Collection::stream);
}
publicstream(){
返回cs.stream().flatMap(Collection::stream);
}

以下是我的解决方案:

编辑-稍微更改代码

public static <E> Iterable<E> concat(final Iterable<? extends E> list1, Iterable<? extends E> list2)
{
    return new Iterable<E>()
    {
        public Iterator<E> iterator()
        {
            return new Iterator<E>()
            {
                protected Iterator<? extends E> listIterator = list1.iterator();
                protected Boolean checkedHasNext;
                protected E nextValue;
                private boolean startTheSecond;

                public void theNext()
                {
                    if (listIterator.hasNext())
                    {
                        checkedHasNext = true;
                        nextValue = listIterator.next();
                    }
                    else if (startTheSecond)
                        checkedHasNext = false;
                    else
                    {
                        startTheSecond = true;
                        listIterator = list2.iterator();
                        theNext();
                    }
                }

                public boolean hasNext()
                {
                    if (checkedHasNext == null)
                        theNext();
                    return checkedHasNext;
                }

                public E next()
                {
                    if (!hasNext())
                        throw new NoSuchElementException();
                    checkedHasNext = null;
                    return nextValue;

                }

                public void remove()
                {
                    listIterator.remove();
                }
            };
        }
    };
}

publicstaticiterable-concat(finaliterable如果您至少使用Java8,请参阅

如果您已经在使用谷歌番石榴,请参阅

如果您仍停留在Java 7上,不想加入Google Guava,那么您可以编写自己的(只读)
Iterables.concat()
,只需使用
Iterable
Iterator

常数
public static Iterable concat(final iterablet这将创建一个新的临时集合,它可能会非常昂贵。如何不复制列表中的底层对象,而
ArrayList
只分配空间并调用
System.arraycopy()
隐藏起来。没有比这更有效的了。如何为每次迭代复制整个集合不昂贵?此外,您可以做得更好,请参见Seans的回答。它还使用本机实现来复制内存,它不会遍历数组。如果它复制数组,它肯定是一个O(n)不可伸缩的算法,其复杂性与在数组上迭代一次相同。假设每个列表包含一百万个元素,那么我需要复制几百万个元素,只需在它们上进行迭代。坏主意。我如何防止用户删除元素?有没有比将列表包装成不可修改的列表更好的方法?@jn_just将其包装在集合中如何?
Iterables.concat
生成一个
Iterable
,而不是
Collection
。我需要一个
Collection
视图。@Damian唯一有用的功能是有一个聚合的size()方法。Collection接口中的所有其他方法都有未定义的语义(add etc)或糟糕的性能(contains etc)。@Sean,是的-
size()
正是我所需要的。
add()
引发异常很好-我不关心这个方法。Collections API已损坏,没有人可以对此做任何事情。
Collection.add()
迭代器.remove()
,诸如此类。您的实现翻转了
hasNext()
next()
的角色。第一个会更改迭代器的状态,而第二个不会。应该是相反的。调用
next()
而不调用
hasNext()
将始终产生
null
。调用
hasNext()
不调用
next()
将丢弃元素。您的
next()
也不会抛出
NoTouchElementException
,而是返回
null
。您重新发明了
org.apache.commons.collections4.iterabluetils.chaineditable()
^断开的链接。我想他指的是