package org.gridkit.jvmtool.event; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; /** * Merges two {@link Iterator} into one. * <br/> * Each of nested {@link Iterator}s MUST produce ordered, duplicate free * sequence of values. * <br/> * Result would be ordered, duplicate free sequence of values present * in either iterator. * * @author Alexey Ragozin (alexey.ragozin@gmail.com) */ public class MergeIterator<T> implements Iterator<T> { @SuppressWarnings("rawtypes") private static final Comparator NATURAL = new NaturalComaprator(); @SuppressWarnings("unchecked") public static <T> Iterator<T> merge(Iterator<T> a, Iterator<T> b) { return merge(a, b, NATURAL); } public static <T> Iterator<T> merge(Iterator<T> a, Iterator<T> b, Comparator<T> cmp) { return new MergeIterator<T>(a, b, cmp); } @SuppressWarnings("unchecked") public static <T> Iterable<T> merge(final Iterable<T> a, final Iterable<T> b) { return merge(a, b, NATURAL); } public static <T> Iterable<T> merge(final Iterable<T> a, final Iterable<T> b, final Comparator<T> cmp) { return new Iterable<T>() { @Override public Iterator<T> iterator() { return merge(a.iterator(), b.iterator(), cmp); } }; } private final Iterator<T> a; private final Iterator<T> b; private final Comparator<T> comparator; private T peekA; private T peekB; @SuppressWarnings("unchecked") public MergeIterator(Iterator<T> a, Iterator<T> b, Comparator<T> cmp) { this.a = a; this.b = b; this.comparator = cmp == null ? NATURAL : cmp; peekA = a.hasNext() ? next(a) : null; peekB = b.hasNext() ? next(b) : null; } private T next(Iterator<T> it) { T v = it.next(); if (v == null) { throw new NullPointerException("null element is not allowed"); } return v; } @Override public boolean hasNext() { return peekA != null || peekB != null; } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } T result; if (peekA == null && peekB != null) { result = peekB; peekB = b.hasNext() ? b.next() : null; } else if (peekB == null && peekA != null) { result = peekA; peekA = a.hasNext() ? a.next() : null; } else { int c = comparator.compare(peekA, peekB); if (c == 0) { result = peekA; peekA = a.hasNext() ? a.next() : null; peekB = b.hasNext() ? b.next() : null; } else if (c > 0) { result = peekB; peekB = b.hasNext() ? b.next() : null; } else { result = peekA; peekA = a.hasNext() ? a.next() : null; } } return result; } @Override public void remove() { throw new UnsupportedOperationException(); } private static class NaturalComaprator implements Comparator<Comparable<Object>> { @Override public int compare(Comparable<Object> o1, Comparable<Object> o2) { return o1.compareTo(o2); } } }