DaveAKing / guava-libraries

Automatically exported from code.google.com/p/guava-libraries
Apache License 2.0
0 stars 0 forks source link

Multirator : an iterator that iterates over other iterators #1727

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hello,

Would you like to add a multirator in Guava ? A multirator (named choosen in 5 
minutes) is an iterator that encapsulates other iterators. I gives the next 
element based on the next elements of the other iterators.

Here is what i looks like :

public interface Multirator<E> extends Iterator<E>, Iterable<E> {
    void add(final Iterator<E>... iterators);
    void add(final Iterable<E>... iterables);
}

I wrote a first implementation who choose the next element as the smallest 
available :

public class SortedPeekingMultirator<E extends Comparable<E>> implements 
Multirator<E> {

    private final List<PeekingIterator<E>> iterators = new ArrayList<>();

    /* Constructors */

    @SafeVarargs
    public SortedPeekingMultirator(final Iterator<E>... iterators) {
        add(iterators);
    }

    @SafeVarargs
    public SortedPeekingMultirator(final Iterable<E>... iterables) {
        add(iterables);
    }

    /* From Multirator.java */

    @SuppressWarnings("unchecked")
    @Override
    public void add(final Iterator<E>... iterators) {
        for (final Iterator<E> iter : iterators) {
            final PeekingIterator<E> pi = Iterators.peekingIterator(iter);
            this.iterators.add(pi);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void add(final Iterable<E>... iterables) {
        for (final Iterable<E> iterable : iterables) {
            add(iterable.iterator());
        }
    }

    /* From Iterator.java */

    @Override
    public boolean hasNext() {

        for (final PeekingIterator<E> pi : iterators) {
            if (pi.hasNext()) {
                return true;
            }
        }

        return false;
    }

    @Override
    public E next() {

        if (!hasNext()) {
            throw new NoSuchElementException();
        }

        E smallest = null;
        int pos = 0;
        int i = 0;

        for (final PeekingIterator<E> pi : iterators) {

            if (!pi.hasNext()) {
                i++;
                continue;
            }

            final E elt = pi.peek();

            if (smallest == null) {
                smallest = elt;
                pos = i++;
                continue;
            }

            if (smallest.compareTo(elt) > 0) {
                smallest = elt;
                pos = i++;
            }
        }

        // next
        iterators.get(pos).next();

        return smallest;
    }
}

Please have a look at the attached files for complete source code and tests.

What do you think about this multirator ?

Thierry

Original issue reported on code.google.com by thierry...@gmail.com on 15 Apr 2014 at 11:29

Attachments:

GoogleCodeExporter commented 9 years ago
Or simpler :

    public E next() {

        if (!hasNext()) {
            throw new NoSuchElementException();
        }

        E smallest = null;
        int pos = 0;
        int i = 0;

        for (final PeekingIterator<E> pi : iterators) {
            if (pi.hasNext()) {
                final E elt = pi.peek();
                if (smallest == null || smallest.compareTo(elt) > 0) {
                    smallest = elt;
                    pos = i;
                }
            }
            i++;
        }

        // next
        iterators.get(pos).next();

        return smallest;
    }

Original comment by thierry...@gmail.com on 15 Apr 2014 at 12:08

GoogleCodeExporter commented 9 years ago
Are you aware of the existing method Iterators.concat(Iterator ...)?:
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect
/Iterators.html#concat%28java.util.Iterator...%29

Original comment by SeanPFl...@googlemail.com on 15 Apr 2014 at 1:30

GoogleCodeExporter commented 9 years ago
Well I was not aware of the method "concat". It looks great. 

But I would say that it does not provide exactly the same thing. With concat, 
you can not specify the order for example. And it works with copies.

Original comment by thierry...@gmail.com on 15 Apr 2014 at 2:00

GoogleCodeExporter commented 9 years ago
Is it really the case that this is a common enough need to be preferable to 
just writing specific iterators for each case?  For the particular example, we 
already have Iterators.mergeSorted.

Original comment by lowas...@google.com on 5 May 2014 at 8:13

GoogleCodeExporter commented 9 years ago
This issue has been migrated to GitHub.

It can be found at https://github.com/google/guava/issues/<id>

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:09

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:17

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 3 Nov 2014 at 9:07