package plume;
import java.util.*;
/**
* Given two sequences/iterators/whatever, this class returns a new
* sequence/iterator/whatever that pairs the matching elements of the
* inputs, according to their respective sort orders. (This opertation is
* sometimes called "zipping".) If the inputs have different lengths, then
* the extra elements at the end of the longer one are paired with null.
*
* <p>
* In some cases this is just the right abstraction. But in some cases
* it's appropriate to use set intersection/difference instead.
*/
// T need not extend Comparable<T>, because a comparator can be passed in.
public class OrderedPairIterator<T> implements java.util.Iterator<Pair</*@Nullable*/ T,/*@Nullable*/ T>> {
Iterator<T> itor1, itor2;
/*@Nullable*/ T next1, next2;
/*@Nullable*/ Comparator<? super T> comparator;
// For this constructor, the arg type is actually Iterator<T extends
// Comparable<T>>, but T is already bound above and can't be changed.
public OrderedPairIterator(Iterator<T> itor1, Iterator<T> itor2) {
this.itor1 = itor1;
this.itor2 = itor2;
setnext1();
setnext2();
}
public OrderedPairIterator(Iterator<T> itor1, Iterator<T> itor2, Comparator<T> comparator) {
this(itor1, itor2);
this.comparator = comparator;
}
/** Set the next1 variable. */
private void setnext1() {
next1 = itor1.hasNext() ? itor1.next() : null;
}
/** Set the next2 variable. */
private void setnext2() {
next2 = itor2.hasNext() ? itor2.next() : null;
}
// Have the caller do this directly, probably.
// public OrderedPairIterator(Set s1, Set s2) {
// this((new TreeSet(s1)).iterator(), (new TreeSet(s2)).iterator());
// }
public boolean hasNext() { return ((next1 != null) || (next2 != null)); }
/** Return an element of the first iterator, paired with null. */
private Pair</*@Nullable*/ T,/*@Nullable*/ T> return1() {
@SuppressWarnings("interning") // bug in interning checker
Pair</*@Nullable*/ T,/*@Nullable*/ T> result = Pair.of(next1, (T)null);
setnext1();
return result;
}
/** Return a pair of null and an element of the second iterator. */
private Pair</*@Nullable*/ T,/*@Nullable*/ T> return2() {
@SuppressWarnings("interning") // bug in interning checker
Pair</*@Nullable*/ T,/*@Nullable*/ T> result = Pair.of((T)null, next2);
setnext2();
return result;
}
/** Return a pair containing an element from each iterator. */
private Pair</*@Nullable*/ T,/*@Nullable*/ T> returnboth() {
Pair</*@Nullable*/ T,/*@Nullable*/ T> result = Pair.of(next1, next2);
setnext1();
setnext2();
return result;
}
public Pair</*@Nullable*/ T,/*@Nullable*/ T> next() {
if (next1 == null) {
if (next2 == null) {
throw new NoSuchElementException();
} else {
return return2();
}
} else {
if (next2 == null) {
return return1();
} else {
int comparison;
// Either T extends Comparable<T>, or else a comparator was passed in.
if (comparator == null) {
@SuppressWarnings("unchecked")
Comparable<T> cble1 = (Comparable<T>)next1;
comparison = cble1.compareTo(next2);
} else {
comparison = comparator.compare(next1, next2);
}
if (comparison < 0)
return return1();
else if (comparison > 0)
return return2();
else
return returnboth();
}
}
}
public void remove() { throw new UnsupportedOperationException(); }
}