在 java 中加入多个迭代器

2022-09-04 03:25:16

有没有人知道如何在Java中加入多个迭代器?我找到的解决方案首先迭代一个迭代器,然后转到下一个迭代器。但是,我想要的是当next()被调用时,它首先从第一个迭代器返回第一个元素。下次调用 next() 时,它将从第二个迭代器返回第一个元素,依此类推。

谢谢


答案 1

使用番石榴的抽象编辑器来简化:

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 +。ArrayDequeLinkedList

如果你真的,真的不能容忍另一个第三方库,你可以或多或少地做一些额外的工作来做同样的事情,比如这样:

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(); }
};

作为参考,“所有 iter1,所有 iter2 等”行为也可以使用 Iterators.concat(Iterator<Iterator>) 及其重载获得。


答案 2

这听起来像是你想要一个交错。像这样的东西 - 完全未经测试...

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();
        }
    }
}