Is it possible to merge iterators in Java?

后端 未结 14 1632
自闭症患者
自闭症患者 2020-11-30 08:14

Is it possible to merge iterators in Java? I have two iterators and I want to combine/merge them so that I could iterate though their elements in one go (in same loop) rathe

相关标签:
14条回答
  • 2020-11-30 09:06

    an iterator comes FROM a collection or a set.
    why not use the method already available
    Collection.addAll(Collection c);
    and then create your iterator from the last object.
    this way, your iterator will iterate all the contents of both collection.

    0 讨论(0)
  • 2020-11-30 09:06

    The Merged Iterator:

    import static java.util.Arrays.asList;
    
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.NoSuchElementException;
    
    
    public class ConcatIterator<T> implements Iterator<T> {
    
        private final List<Iterable<T>> iterables;
        private Iterator<T> current;
    
        @SafeVarargs
        public ConcatIterator(final Iterable<T>... iterables) {
            this.iterables = new LinkedList<>(asList(iterables));
        }
    
        @Override
        public boolean hasNext() {
            checkNext();
            return current != null && current.hasNext();
        }
    
        @Override
        public T next() {
            checkNext();
            if (current == null || !current.hasNext()) throw new NoSuchElementException();
            return current.next();
        }
    
        @Override
        public void remove() {
            if (current == null) throw new IllegalStateException();
            current.remove();
        }
    
        private void checkNext() {
            while ((current == null || !current.hasNext()) && !iterables.isEmpty()) {
                current = iterables.remove(0).iterator();
            }
        }
    
    }
    

    The concat method to create an Iterable:

    @SafeVarargs
    public static <T> Iterable<T> concat(final Iterable<T>... iterables) {
        return () -> new ConcatIterator<>(iterables);
    }
    

    Simple JUnit test:

    @Test
    public void testConcat() throws Exception {
        final Iterable<Integer> it1 = asList(1, 2, 3);
        final Iterable<Integer> it2 = asList(4, 5);
        int j = 1;
        for (final int i : concat(it1, it2)) {
            assertEquals(j, i);
            j++;
        }
    }
    
    0 讨论(0)
  • 2020-11-30 09:08

    Starting with Java 8 and later this can be done without external dependencies using Stream API. This also allows concatenation of iterator with other types of streams.

    Streams.concat(StreamSupport.stream(<iter1>, false), StreamSupport.stream(<iter2>, false));
    
    0 讨论(0)
  • 2020-11-30 09:09

    You could create your own implementation of the Iterator interface which iterates over the iterators:

    public class IteratorOfIterators implements Iterator {
        private final List<Iterator> iterators;
    
        public IteratorOfIterators(List<Iterator> iterators) {
            this.iterators = iterators;
        }
    
        public IteratorOfIterators(Iterator... iterators) {
            this.iterators = Arrays.asList(iterators);
        }
    
    
        public boolean hasNext() { /* implementation */ }
    
        public Object next() { /* implementation */ }
    
        public void remove() { /* implementation */ }
    }
    

    (I've not added generics to the Iterator for brevity.) The implementation is not too hard, but isn't the most trivial, you need to keep track of which Iterator you are currently iterating over, and calling next() you'll need to iterate as far as you can through the iterators until you find a hasNext() that returns true, or you may hit the end of the last iterator.

    I'm not aware of any implementation that already exists for this.

    Update:
    I've up-voted Andrew Duffy's answer - no need to re-invent the wheel. I really need to look into Guava in more depth.

    I've added another constructor for a variable number of arguments - almost getting off topic, as how the class is constructed here isn't really of interest, just the concept of how it works.

    0 讨论(0)
  • 2020-11-30 09:11

    move your loop to a method and pass the iterator to method.

    void methodX(Iterator x) {
        while (x.hasNext()) {
            ....
        }
    }
    
    0 讨论(0)
  • 2020-11-30 09:12

    Guava (formerly Google Collections) has Iterators.concat.

    0 讨论(0)
提交回复
热议问题