有人知道如何在Java中加入多个迭代器吗?我发现的解决方案首先迭代一个迭代器,然后继续下一个迭代器。但是,我想要的是当next()被调用时,它首先返回第一个迭代器中的第一个元素。下次调用next()时,它将返回第二个迭代器中的第一个元素,依此类推。
由于
答案 0 :(得分:10)
为简单起见,请使用Guava's AbstractIterator
:
final List<Iterator<E>> theIterators;
return new AbstractIterator<E>() {
private Queue<Iterator<E>> queue = new LinkedList<Iterator<E>>(theIterators);
@Override protected E computeNext() {
while(!queue.isEmpty()) {
Iterator<E> topIter = queue.poll();
if(topIter.hasNext()) {
E result = topIter.next();
queue.offer(topIter);
return result;
}
}
return endOfData();
}
};
这将为您提供所需的“交错”顺序,它足够智能地处理具有不同大小的集合,并且它非常紧凑。 (假设您使用的是Java 6 +,您可能希望使用ArrayDeque
代替LinkedList
来提高速度。)
如果你真的,真的不能容忍另一个第三方库,你可以或多或少地通过一些额外的工作做同样的事情,如下:
return new Iterator<E>() {
private Queue<Iterator<E>> queue = new LinkedList<Iterator<E>>(theIterators);
public boolean hasNext() {
// If this returns true, the head of the queue will have a next element
while(!queue.isEmpty()) {
if(queue.peek().hasNext()) {
return true;
}
queue.poll();
}
return false;
}
public E next() {
if(!hasNext()) throw new NoSuchElementException();
Iterator<E> iter = queue.poll();
E result = iter.next();
queue.offer(iter);
return result;
}
public void remove() { throw new UnsupportedOperationException(); }
};
作为参考,也可以使用Iterators.concat(Iterator<Iterator>)
及其重载来获取“所有iter1,所有iter2等”行为。
答案 1 :(得分:3)
听起来你想要交错。这样的事情 - 完全未经测试......
public class InterleavingIterable<E> implements Iterable<E> {
private final Iterable<? extends E> first;
private final Iterable<? extends E> second;
public InterleavingIterable(Iterable<? extends E> first,
Iterable<? extends E> second) {
this.first = first;
this.second = second;
}
public Iterator<E> iterator() {
return new InterleavingIterator<E>(first.iterator(),
second.iterator());
}
private static class InterleavingIterator<E> implements Iterator<E> {
private Iterator<? extends E> next;
private Iterator<? extends E> current;
private InterleavingIterator(Iterator<? extends E> first,
Iterator<? extends E> second) {
next = first;
current = second;
}
public boolean hasNext() {
return next.hasNext() || (current != null && current.hasNext());
}
public E next() throws NoSuchElementException {
if (next.hasNext()) {
E ret = next.next();
if (current != null) {
Iterator<? extends E> tmp = current;
current = next;
next = tmp;
}
return ret;
} else {
// Nothing left in next... check "current"
if (current == null || !current.hasNext()) {
throw new NoSuchElementException();
}
next = current;
current = null;
return current.next();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
答案 2 :(得分:0)
编辑: 哎呀,误解了你的问题。 实际上你需要一个交错迭代器,而不是复合迭代器:
class InterleavingIterator<T> implements Iterator<T> {
private final Iterator<T> internalIter;
public InterleavingIterator(final Iterator<T>... iterators) {
final LinkedList<Iterator<T>> iteratorQueue = new LinkedList<Iterator<T>>();
for (final Iterator<T> loopIter : iterators) {
if (loopIter.hasNext()) {
iteratorQueue.push(loopIter);
}
}
// create the interleaving
final LinkedList<T> internalList = new LinkedList<T>();
while (!iteratorQueue.isEmpty()) {
final Iterator<T> loopIter = iteratorQueue.pop();
internalList.add(loopIter.next());
if (loopIter.hasNext()) {
iteratorQueue.push(loopIter);
}
}
internalIter = internalList.iterator();
}
public boolean hasNext() {
return internalIter.hasNext();
}
public T next() {
return internalIter.next();
}
public void remove() {
throw new UnsupportedOperationException("remove() unsupported");
}
}
结束编辑。
您需要使用复合迭代器,例如:
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
public class CompoundIterator<T> implements Iterator<T> {
private final LinkedList<Iterator<T>> iteratorQueue;
private Iterator<T> current;
public CompoundIterator(final Iterator<T>... iterators) {
this.iteratorQueue = new LinkedList<Iterator<T>>();
for (final Iterator<T> iterator : iterators) {
iteratorQueue.push(iterator);
}
current = Collections.<T>emptyList().iterator();
}
public boolean hasNext() {
final boolean curHasNext = current.hasNext();
if (!curHasNext && !iteratorQueue.isEmpty()) {
current = iteratorQueue.pop();
return current.hasNext();
} else {
return curHasNext;
}
}
public T next() {
if (current.hasNext()) {
return current.next();
}
if (!iteratorQueue.isEmpty()) {
current = iteratorQueue.pop();
}
return current.next();
}
public void remove() {
throw new UnsupportedOperationException("remove() unsupported");
}
}
答案 3 :(得分:-1)
最简单的方法是
for(Type1 t1: collection1)
for(Type2 t2: collection2)
如果您希望它在集合之间执行连接,这将有效。
如果你想迭代两个集合,我只会使用两个循环或用两者创建一个集合。
for(Type t1: collection1)
process(t1);
for(Type t2: collection2)
process(t2);
如果你想交错迭代器,你可以使用数组。
Iterator[] iters = { iter1, iter2, ... };
boolean finished;
do {
finished = true;
for(Iterator it: iters) {
if (it.hasNext()) {
Object obj = it.next();
// process
finished = false;
}
}
} while(!finished);