2012-02-08 27 views
12

Có ai biết cách kết nối nhiều bộ lặp trong Java không? Giải pháp tôi tìm thấy lặp qua một trình vòng lặp đầu tiên, và sau đó chuyển sang bước tiếp theo. Tuy nhiên, những gì tôi muốn là khi next() được gọi, nó đầu tiên trả về phần tử đầu tiên từ trình lặp đầu tiên. Lần tới khi hàm next() được gọi, nó trả về phần tử đầu tiên từ trình lặp thứ hai, v.v.tham gia nhiều trình lặp trong java

Cảm ơn

+0

Nhiều lặp với cùng bộ sưu tập hoặc từng iterator từ bộ sưu tập khác nhau? – kosa

+2

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

+0

@RobertPeters Yeah trông giống như một bản dupe. flyingfromchina, bạn có thể đăng một ví dụ về những gì bạn muốn làm rõ câu hỏi? – daveslab

Trả lời

10

Sử dụng Guava'sAbstractIterator vì đơn giản:

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

này sẽ cung cấp cho bạn những mong muốn "xen kẽ" trật tự, nó đủ thông minh để đối phó với những bộ sưu tập có kích cỡ khác nhau, và nó khá nhỏ gọn. (Bạn có thể muốn sử dụng ArrayDeque thay cho số LinkedList cho tốc độ, giả sử bạn đang sử dụng Java 6+.)

Nếu bạn thực sự, không thể chịu đựng được thư viện của bên thứ ba khác, bạn có thể làm nhiều hơn hoặc ít hơn điều tương tự với một số công việc bổ sung, như vậy:

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

để tham khảo, "tất cả các iter1, tất cả iter2, vv" hành vi cũng có thể thu được bằng Iterators.concat(Iterator<Iterator>) và quá tải của nó.

-1

Phương pháp đơn giản nhất là

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

này sẽ làm việc nếu những gì bạn muốn nó để thực hiện một tham gia giữa các bộ sưu tập.

Nếu bạn muốn lặp lại hai bộ sưu tập, tôi sẽ chỉ sử dụng hai vòng hoặc tạo một bộ sưu tập với cả hai.

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

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

Nếu bạn muốn xen kẽ Iterators bạn có thể sử dụng mảng.

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 Tôi nghĩ rằng anh ta có hiệu quả muốn Coll1.get (0), Coll2.get (0), Coll1.get (1), Coll2.get (1) - tức là xen kẽ, không lồng nhau – Bohemian

+5

Tôi không nghĩ rằng sẽ làm những gì được yêu cầu, phải không? –

+0

Điều này có chạy không? Đối với mỗi mục trong t1, tất cả các mục trong t2 ?? – noMAD

3

Có vẻ như bạn muốn xen kẽ. Một cái gì đó như thế này - hoàn toàn chưa được kiểm tra ...

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

Chỉnh sửa: Rất tiếc, đã giải thích sai câu hỏi của bạn. Bạn thực sự cần một iterator interleaving, thay vì một iterator hợp chất:

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

End chỉnh sửa.

Bạn cần phải sử dụng một iterator hợp chất, một cái gì đó như:

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