将多个 Iterable 包装成一个 Interable

发布于 2024-10-25 20:42:47 字数 915 浏览 1 评论 0原文

假设我有两个 Collections:

Collection< Integer > foo = new ArrayList< Integer >();
Collection< Integer > bar = new ArrayList< Integer >();

并假设有时我想单独迭代它们,但有时会一起迭代它们。有没有办法围绕 foobar 创建一个包装器,以便我可以迭代组合对,但每当 foo 时也会更新它和 bar 改变吗? (即 Collection.addAll() 不合适)。

例如:

Collection< Integer > wrapper = ... // holds references to both bar and foo

foo.add( 1 );
bar.add( 99 );

for( Integer fooInt : foo ) {
    System.out.println( fooInt );
} // output: 1

for( Integer barInt : bar ) {
    System.out.println( barInt );
} // output: 99

for( Integer wrapInt : wrapper ) {
    System.out.println( wrapInt );
} // output: 1, 99

foo.add( 543 );

for( Integer wrapInt : wrapper ) {
    System.out.println( wrapInt );
} // output: 1, 99, 543

谢谢!

Say I have two Collections:

Collection< Integer > foo = new ArrayList< Integer >();
Collection< Integer > bar = new ArrayList< Integer >();

and say sometimes I would like to iterate over them individually, but sometimes together. Is there a way to create a wrapper around foo and bar so that I can iterate over the combined pair, but which is also updated whenever foo and bar change? (i.e. Collection.addAll() is not suitable).

For example:

Collection< Integer > wrapper = ... // holds references to both bar and foo

foo.add( 1 );
bar.add( 99 );

for( Integer fooInt : foo ) {
    System.out.println( fooInt );
} // output: 1

for( Integer barInt : bar ) {
    System.out.println( barInt );
} // output: 99

for( Integer wrapInt : wrapper ) {
    System.out.println( wrapInt );
} // output: 1, 99

foo.add( 543 );

for( Integer wrapInt : wrapper ) {
    System.out.println( wrapInt );
} // output: 1, 99, 543

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

究竟谁懂我的在乎 2024-11-01 20:42:47

使用 GuavaIterables.concat< /a> 方法。

Iterable<Integer> wrapped = Iterables.concat(foo, bar);

Use Guava's Iterables.concat methods.

Iterable<Integer> wrapped = Iterables.concat(foo, bar);
辞取 2024-11-01 20:42:47

我为此编写了两个函数:

/**
 * Create an Iterator from multiple Iterators. The returned Iterator
 * traverses all elements from all sources, in the order, as if they belong
 * to the same source.
 * 
 * @param <T> type of elements
 * @param sources sources of the elements, in order of traversal
 * @return an iterator over multiple iterators in sequence
 */
public static <T> Iterator<T> concatenate(final Iterator<T> ... sources) {
    if (sources.length == 0) {
        return new Iterator<T>() {
            @Override public boolean hasNext() { return false; }
            @Override public T next() { throw new NoSuchElementException("end of iteration"); }
            @Override public void remove() { throw new IllegalStateException("no previous element"); }
        };
    }
    return new Iterator<T>() {

        Iterator<Iterator<T>> sourcesIterator = Arrays.asList(sources).iterator();
        Iterator<T> currentIterator = sourcesIterator.next();

        @Override
        public boolean hasNext() {
            if (currentIterator.hasNext()) {
                return true;
            } else {
                if (sourcesIterator.hasNext()) {
                    currentIterator = sourcesIterator.next();
                    return hasNext();
                } else {
                    return false;
                }
            }
        }

        @Override
        public T next() {
            if (hasNext()) {
                return currentIterator.next();
            } else {
                throw new NoSuchElementException("end of iteration");
            }
        }

        @Override
        public void remove() {
            currentIterator.remove();
        }
    };
}

/**
 * Create an Iterable from multiple Iterables. The returned Iterable
 * traverses all elements from all sources, in the order, as if they belong
 * to the same source.
 * 
 * @param <T> type of elements
 * @param sources sources of the elements, in order of traversal
 * @return an iterable over multiple iterators in sequence
 */
@SuppressWarnings("unchecked") // impossible to create a generic array
public static <T> Iterable<T> concatenate(final Iterable<T> ... sources) {
    return new Iterable<T>() {
        @Override
        public Iterator<T> iterator() {
            final Iterator[] iteratorsArrays = new Iterator[sources.length];
            for (int i = 0; i < sources.length; i++) {
                iteratorsArrays[i] = sources[i].iterator();
            }
            return concatenate(iteratorsArrays);
        }
    };
}

I wrote two functions for that :

/**
 * Create an Iterator from multiple Iterators. The returned Iterator
 * traverses all elements from all sources, in the order, as if they belong
 * to the same source.
 * 
 * @param <T> type of elements
 * @param sources sources of the elements, in order of traversal
 * @return an iterator over multiple iterators in sequence
 */
public static <T> Iterator<T> concatenate(final Iterator<T> ... sources) {
    if (sources.length == 0) {
        return new Iterator<T>() {
            @Override public boolean hasNext() { return false; }
            @Override public T next() { throw new NoSuchElementException("end of iteration"); }
            @Override public void remove() { throw new IllegalStateException("no previous element"); }
        };
    }
    return new Iterator<T>() {

        Iterator<Iterator<T>> sourcesIterator = Arrays.asList(sources).iterator();
        Iterator<T> currentIterator = sourcesIterator.next();

        @Override
        public boolean hasNext() {
            if (currentIterator.hasNext()) {
                return true;
            } else {
                if (sourcesIterator.hasNext()) {
                    currentIterator = sourcesIterator.next();
                    return hasNext();
                } else {
                    return false;
                }
            }
        }

        @Override
        public T next() {
            if (hasNext()) {
                return currentIterator.next();
            } else {
                throw new NoSuchElementException("end of iteration");
            }
        }

        @Override
        public void remove() {
            currentIterator.remove();
        }
    };
}

/**
 * Create an Iterable from multiple Iterables. The returned Iterable
 * traverses all elements from all sources, in the order, as if they belong
 * to the same source.
 * 
 * @param <T> type of elements
 * @param sources sources of the elements, in order of traversal
 * @return an iterable over multiple iterators in sequence
 */
@SuppressWarnings("unchecked") // impossible to create a generic array
public static <T> Iterable<T> concatenate(final Iterable<T> ... sources) {
    return new Iterable<T>() {
        @Override
        public Iterator<T> iterator() {
            final Iterator[] iteratorsArrays = new Iterator[sources.length];
            for (int i = 0; i < sources.length; i++) {
                iteratorsArrays[i] = sources[i].iterator();
            }
            return concatenate(iteratorsArrays);
        }
    };
}
神仙妹妹 2024-11-01 20:42:47

查看 Apache Commons Collections - CollectionUtils 或 IteratorUtils。它们具有您正在寻找的方法类型。

Check out Apache Commons Collections - CollectionUtils or IteratorUtils. The have the type of methods you are looking for.

昨迟人 2024-11-01 20:42:47

一个简单的 List 的 List 并不是那么多的样板文件:

List <List <Integer>> metalist = new ArrayList <List <Integer>> ();
metalist.add (foo);
metalist.add (bar);
for (List<Integer> list : metalist) 
    for (Integer wrapInt : list)
        System.out.println (wrapInt);

如果你现在将 4 添加到 foo foo.add (4); 中,你只需重复 2 个循环即可。问题出在哪里?

A simple List of List isn't that much boilerplate:

List <List <Integer>> metalist = new ArrayList <List <Integer>> ();
metalist.add (foo);
metalist.add (bar);
for (List<Integer> list : metalist) 
    for (Integer wrapInt : list)
        System.out.println (wrapInt);

If you now add 4 to foo foo.add (4); you just repeat the 2 loops. Where is the problem?

Oo萌小芽oO 2024-11-01 20:42:47

像@barjak,但更短

public static <E> Collection<E> concat(Collection<E> ... es) {
    List<E> ret = new ArrayList<E>();
    for (Collection<E> e : es) ret.addAll(e);
    return ret;
}

public static <E> Iterable<E> viewOf(final Collection<E> ... es) {
    return new Iterable<E>() {
        public Iterator<E> iterator() {
            return concat(es).iterator();
        }
    };
}

Collection< Integer > foo = new ArrayList< Integer >();
Collection< Integer > bar = new ArrayList< Integer >();

// call as often as you like.
for(Integer i : concat(foo, bar))

// OR
Iterable<Integer> view = viewOf(foo, bar);

// call as often as you like.
for(Integer i : view)

Like @barjak, but shorter

public static <E> Collection<E> concat(Collection<E> ... es) {
    List<E> ret = new ArrayList<E>();
    for (Collection<E> e : es) ret.addAll(e);
    return ret;
}

public static <E> Iterable<E> viewOf(final Collection<E> ... es) {
    return new Iterable<E>() {
        public Iterator<E> iterator() {
            return concat(es).iterator();
        }
    };
}

Collection< Integer > foo = new ArrayList< Integer >();
Collection< Integer > bar = new ArrayList< Integer >();

// call as often as you like.
for(Integer i : concat(foo, bar))

// OR
Iterable<Integer> view = viewOf(foo, bar);

// call as often as you like.
for(Integer i : view)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文