2012-02-08 27 views
12

Java'da birden çok yineleyiciye nasıl katılacağını bilen var mı? Ben bulduğum çözüm önce bir yineleyici ile yineleyin ve sonra bir sonrakine geçin. Ancak, istediğim, sonraki() çağrıldığında, ilk öğeyi ilk yineleyiciden döndürür. Sonraki() çağrıldığında, ikinci öğeden ilk öğeyi döndürür ve böyle devam eder.java'da birden çok yineleyiciye katılın

Teşekkür

+0

Çoklu yineleyiciler:

Sen, bir bileşik tekrarlayıcı kullanmak gibi bir şey gerekir? – kosa

+2

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

+0

@RobertPeters Evet bir dupe gibi görünüyor. flyingfromchina, soruyu açıklığa kavuşturmak istediğin şeyin bir örneğini gönderebilir misin? – daveslab

cevap

10

basitlik için Guava'sAbstractIterator kullanma:

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

Bu, arzu edilen "Interleaved" emri verecek, bu koleksiyonları farklı boyutlara sahip başa kadar akıllı ve oldukça kompakt bu. (Java 6+ üzerindeyseniz, ArrayDeque'u LinkedList yerine hız için kullanmak isteyebilirsiniz.)

Eğer gerçekten başka bir üçüncü taraf kitaplığını tolere edemiyorsanız, daha fazlasını yapabilirsiniz. böylece gibi bazı ek iş, aynı şey: referans olarak

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 hepsi iter2 tüm vb" davranış Iterators.concat(Iterator<Iterator>) ve aşırı yükleri kullanılarak elde edilebilir.

-1

en basit yaklaşım

for(Type1 t1: collection1) 
    for(Type2 t2: collection2) 

istediğini bir koleksiyonlar arasında birleştirme gerçekleştirmek için bu çalışacaktır olduğunu.

İki koleksiyon yinelemek isterseniz, iki döngüyü kullanırım veya her ikisiyle de bir koleksiyon oluştururdum. Eğer yineleyiciler serpiştirmek istiyorum

for(Type t1: collection1) 
    process(t1); 

for(Type t2: collection2) 
    process(t2); 

bir dizi kullanabilirsiniz.

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

Hmmm Bence etkili bir şekilde Coll1.get (0), Coll2.get (0), Coll1.get (1), Coll2.get (1) - yani interleaved, nested değil – Bohemian

+5

Bunun ne olacağını düşünmüyorum talep etti mi? –

+0

Bu gereksiz yere kaçmaz mıydı? T1'deki her öğe için, t2'deki tüm öğeler? – noMAD

3

aralıklı araya girmek istediğiniz gibi geliyor. Böyle bir şey - tamamen denenmemiş ...

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

Düzenleme: Üzgünüz, sorunuzu yanlış. Aslında yerine bileşik yineleyici bir araya girme yineleyici gerekir:

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

sonu düzenlemek. Aynı koleksiyon veya farklı koleksiyondan her yineleyici için

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