说我有两个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
谢谢!
答案 0 :(得分:5)
使用Guava的Iterables.concat方法。
Iterable<Integer> wrapped = Iterables.concat(foo, bar);
答案 1 :(得分:3)
我写了两个函数:
/**
* 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);
}
};
}
答案 2 :(得分:0)
查看Apache Commons Collections - CollectionUtils或IteratorUtils。有你想要的方法类型。
答案 3 :(得分:0)
一个简单的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);
如果现在向foo foo.add (4);
添加4,则只需重复2次循环。问题出在哪儿?
答案 4 :(得分:-1)
喜欢@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)