【问题标题】:join multiple iterators in java在java中加入多个迭代器
【发布时间】:2012-03-01 06:53:36
【问题描述】:

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

谢谢

【问题讨论】:

  • 多个迭代器指向同一个集合还是每个迭代器来自不同的集合?
  • @RobertPeters 是的,看起来像个骗子。 flyfromchina,你能发布一个你想澄清问题的例子吗?
  • 我不相信这是一个骗局,因为链接的问题没有要求这个问题要求的特定迭代顺序(并且它的答案不符合 OP 的标准)。

标签: java iterator


【解决方案1】:

为简单起见,使用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&lt;Iterator&gt;) 及其重载来获得“所有 iter1、所有 iter2 等”行为。

【讨论】:

    【解决方案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();
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      编辑: 糟糕,误解了你的问题。 您实际上需要一个交错迭代器,而不是复合迭代器:

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

      【讨论】:

        【解决方案4】:

        最简单的方法是

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

        【讨论】:

        • 嗯,我认为他实际上想要 Coll1.get(0), Coll2.get(0), Coll1.get(1), Coll2.get(1) - 即交错,而不是嵌套
        • 我认为这不会满足要求,对吧?
        • 这不会冗余运行吗?对于 t1 中的每个项目,t2 中的所有项目??
        • 在第一种情况下,是的。这就是没有约束时数据库中的表 JOIN 所做的事情。
        猜你喜欢
        • 1970-01-01
        • 2014-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-14
        • 2015-09-12
        • 2011-07-15
        • 1970-01-01
        相关资源
        最近更新 更多