package org.gridkit.jvmtool.event; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; /** * Subtract one {@link Iterator} from another. * <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 iterator A, but not present in V. * * @author Alexey Ragozin (alexey.ragozin@gmail.com) */ public class ExcludeIterator<T> implements Iterator<T> { @SuppressWarnings("rawtypes") private static final Comparator NATURAL = new NaturalComaprator(); @SuppressWarnings("unchecked") public static <T> Iterator<T> exclude(Iterator<T> a, Iterator<T> b) { return exclude(a, b, NATURAL); } public static <T> Iterator<T> exclude(Iterator<T> a, Iterator<T> b, Comparator<T> cmp) { return new ExcludeIterator<T>(a, b, cmp); } @SuppressWarnings("unchecked") public static <T> Iterable<T> exclude(final Iterable<T> a, final Iterable<T> b) { return exclude(a, b, NATURAL); } public static <T> Iterable<T> exclude(final Iterable<T> a, final Iterable<T> b, final Comparator<T> cmp) { return new Iterable<T>() { @Override public Iterator<T> iterator() { return exclude(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 ExcludeIterator(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; seek(); } private T next(Iterator<T> it) { T v = it.next(); if (v == null) { throw new NullPointerException("null element is not allowed"); } return v; } private void seek() { while(peekA != null && peekB != null) { int c = comparator.compare(peekA, peekB); if (c > 0) { peekB = b.hasNext() ? b.next() : null; continue; } else if (c == 0) { peekA = a.hasNext() ? a.next() : null; peekB = b.hasNext() ? b.next() : null; continue; } else { break; } } } @Override public boolean hasNext() { return peekA != null; } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } T result = peekA; peekA = a.hasNext() ? a.next() : null; seek(); 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); } } }