Упаковка нескольких итераций в один Interable - PullRequest
3 голосов
/ 24 марта 2011

Скажите, что у меня есть два Collections:

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

и скажите, что иногда я хотел бы выполнять их по отдельности, но иногда вместе.Есть ли способ создать обертку вокруг foo и bar, чтобы я мог выполнять итерацию по объединенной паре, но который также обновляется при изменении 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

Спасибо!

Ответы [ 5 ]

5 голосов
/ 24 марта 2011

Использование Гуава * Iterables.concat методы.

Iterable<Integer> wrapped = Iterables.concat(foo, bar);
3 голосов
/ 24 марта 2011

Для этого я написал две функции:

/**
 * 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);
        }
    };
}
0 голосов
/ 25 марта 2011

Простой список не так уж и прост:

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 цикла. В чем проблема?

0 голосов
/ 24 марта 2011

Как @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)
0 голосов
/ 24 марта 2011

Извлечение Коллекции Apache Commons - CollectionUtils или IteratorUtils. Есть тип методов, которые вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...