What should be the return type of a zip function? (zip as in most other languages, e.g. read here)
zip
I thought about some Pair-type but that
I think I have made pair class tuned almost to perfection :P
public class Pair implements Iterable, Cloneable{ public static Pair makePair(X x, Y y){ return new Pair(x, y); } public static Pair makePairFromArray(X... xs){ if (xs.length == 0) return new Pair(null, null); if (xs.length == 1) return new Pair(xs[0], null); return new Pair(xs[0], Arrays.copyOfRange(xs, 1, xs.length-1)); } public static Pair reverse(Pair original){ return makePair(original.getSecond(), original.getFirst()); } public static synchronized void swap(Pair swapped){ X tmp = swapped.getFirst(); swapped.setFirst(swapped.getSecond()); swapped.setSecond(tmp); } @SuppressWarnings("unchecked") public static List asObjectList(Pair pair){ return asList((Pair) pair); } public static Object[] asObjectArray(Pair pair, Object[] array){ return asObjectList(pair).toArray(array); } public static List asList(Pair pair){ ArrayList list = new ArrayList(); list.add(pair.getFirst()); list.add(pair.getSecond()); return list; } public static X[] asArray(Pair pair, X[] array){ return asList(pair).toArray(array); } public static Iterator typedIterator(Pair pair){ @SuppressWarnings("unchecked") final Iterator it = (Iterator) pair.iterator(); return it; } public static boolean isSymmetric(Pair pair){ return pair.equals(reverse(pair)); } public static boolean isReflexive(Pair pair){ X x1 = pair.getFirst(); X x2 = pair.getSecond(); if (x1 == null && x2 == null) return true; if (x1 == null && x2 != null) return false; if (x1 != null && x2 == null) return false; return x1.equals(x2); } public static boolean isTransitive(Pair first, Pair second){ Y y1 = first.getSecond(); Y y2 = second.getFirst(); if (y1 == null && y2 == null) return true; if (y1 == null && y2 != null) return false; if (y1 != null && y2 == null) return false; return y1.equals(y2); } public static synchronized Pair immutablePair(Pair pair){ final Pair wrapped = pair; return new Pair(null, null){ @Override public X getFirst() { return wrapped.getFirst(); } @Override public Y getSecond() { return wrapped.getSecond(); } @Override public void setFirst(X first) { throw new UnsupportedOperationException(); } @Override public void setSecond(Y second) { throw new UnsupportedOperationException(); } @Override public int hashCode() { return wrapped.hashCode(); } @Override public boolean equals(Object obj) { return wrapped.equals(obj); } @Override public String toString() { return wrapped.toString(); } @Override public Iterator iterator() { return wrapped.iterator(); } @Override public Object clone() throws CloneNotSupportedException { return wrapped.clone(); } @Override public Pair copy() { return wrapped.copy(); } }; } public static synchronized Pair synchronizedPair(Pair pair){ final Pair wrapped = pair; return new Pair(null, null){ @Override public synchronized X getFirst() { return wrapped.getFirst(); } @Override public synchronized void setFirst(X first) { wrapped.setFirst(first); } @Override public synchronized Y getSecond() { return wrapped.getSecond(); } @Override public synchronized void setSecond(Y second) { wrapped.setSecond(second); } @Override public synchronized int hashCode() { return wrapped.hashCode(); } @Override public synchronized boolean equals(Object obj) { return wrapped.equals(obj); } @Override public synchronized String toString() { return wrapped.toString(); } @Override public synchronized Iterator iterator() { return wrapped.iterator(); } @Override public synchronized Object clone() throws CloneNotSupportedException { return wrapped.clone(); } @Override public synchronized Pair copy() { return wrapped.copy(); } }; } public Pair(T1 first, T2 second) { super(); this.first = first; this.second = second; } public Pair(){ super(); this.first = null; this.second = null; } public Pair(Pair copy) { first = copy.first; second = copy.second; } private T1 first; private T2 second; public T1 getFirst() { return first; } public void setFirst(T1 first) { this.first = first; } public T2 getSecond() { return second; } public void setSecond(T2 second) { this.second = second; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((second == null) ? 0 : second.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; @SuppressWarnings("rawtypes") Pair other = (Pair) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (second == null) { if (other.second != null) return false; } else if (!second.equals(other.second)) return false; return true; } @Override public String toString() { return "(" + first + ", " + second + ")"; } @Override public Iterator iterator() { return new Iterator(){ private int it = 0; @Override public boolean hasNext() { return it != 2; } @Override public Object next() { return (it++) == 0 ? first : second; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } public Pair copy(){ return makePair(first, second); } }