2012-02-08 7 views
12

Java에서 다중 반복기에 참여하는 방법을 아는 사람이 있습니까? 발견 된 솔루션은 먼저 하나의 반복자를 통해 반복하고, 다음 반복으로 이동합니다. 그러나, 내가 원하는 것은 next()가 호출되면, 첫 번째 요소를 첫 번째 이터레이터에서 반환합니다. 다음에 next()가 호출되면 두 번째 이터레이터에서 첫 번째 요소를 반환하는 식으로 계속됩니다.자바의 다중 반복기에 참여하십시오.

감사

+0

여러 반복자 :

당신은 복합 반복자를 사용하는 같은 뭔가가 필요? – kosa

+2

Yikes : http://stackoverflow.com/questions/3610261/is-it-possible-to-merge-iterators-in-java –

+0

@RobertPeters 그래, 속는 사람 같아. flyingfromchina, 당신이 질문을 명확히하고 싶은 것의 예를 게시 할 수 있습니까? – daveslab

답변

10

편의를 위해 Guava'sAbstractIterator 사용 :

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을 사용하여 속도를 향상시킬 수 있습니다.)

다른 타사 라이브러리를 정말로 용인 할 수 없다면 더 많은 그래서 같은 몇 가지 추가 작업과 같은 일이 : 참고로

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>)하고 오버로드를 사용하여 얻을 수 있습니다.

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

흠. 그가 효과적으로 원하는 것 같아요. Coll1.get (0), Coll2.get (0), Coll1.get (1), Coll2.get (1) - 중첩되지 않은 인터리브. – Bohemian

+5

요청 했어? –

+0

중복 실행되지 않습니까? t1의 모든 항목에 대해 t2의 모든 항목 ?? – noMAD

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(); 
     } 
    } 
} 
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"); 
    } 
} 
관련 문제