001package org.clafer.collection; 002 003import java.lang.reflect.Array; 004import java.util.ArrayList; 005import java.util.List; 006import org.clafer.common.Check; 007 008/** 009 * A 2-tuple. 010 * 011 * 012 * @param <A> the type of fst 013 * @param <B> the type of snd 014 * @author jimmy 015 */ 016public class Pair<A, B> { 017 018 private final A fst; 019 private final B snd; 020 021 /** 022 * Construct a tuple. 023 * 024 * @param fst 025 * @param snd 026 */ 027 public Pair(A fst, B snd) { 028 this.fst = Check.notNull(fst); 029 this.snd = Check.notNull(snd); 030 } 031 032 public Pair(Pair<? extends A, ? extends B> pair) { 033 this(pair.getFst(), pair.getSnd()); 034 } 035 036 public A getFst() { 037 return fst; 038 } 039 040 public B getSnd() { 041 return snd; 042 } 043 044 /** 045 * Returns the first element of the tuples in the same order. Equivalent to 046 * the Haskell code {@code map fst}. 047 * 048 * @param <A> the type of first element in the pairs 049 * @param <B> the type of second element in the pairs 050 * @param pairs the tuples 051 * @return the first element of the tuples 052 */ 053 public static <A, B> List<A> mapFst(List<Pair<A, B>> pairs) { 054 List<A> fsts = new ArrayList<>(pairs.size()); 055 for (Pair<A, B> pair : pairs) { 056 fsts.add(pair.getFst()); 057 } 058 return fsts; 059 } 060 061 /** 062 * Returns the first element of the tuples in the same order. Equivalent to 063 * the Haskell code {@code map fst}. 064 * 065 * @param <A> the type of first element in the pairs 066 * @param <B> the type of second element in the pairs 067 * @param pairs the tuples 068 * @param array the array to write to if the size is correct 069 * @return the first element of the tuples 070 */ 071 @SafeVarargs 072 public static <A, B> A[] mapFst(Pair<A, B>[] pairs, A... array) { 073 @SuppressWarnings("unchecked") 074 A[] to = array.length == pairs.length 075 ? array 076 : (A[]) Array.newInstance(array.getClass().getComponentType(), pairs.length); 077 for (int i = 0; i < to.length; i++) { 078 to[i] = pairs[i].getFst(); 079 } 080 return to; 081 } 082 083 /** 084 * Returns the second element of the tuples in the same order. Equivalent to 085 * the Haskell code {@code map snd}. 086 * 087 * @param <A> the type of first element in the pairs 088 * @param <B> the type of second element in the pairs 089 * @param pairs the tuples 090 * @return the second element of the tuples 091 */ 092 public static <A, B> List<B> mapSnd(List<Pair<A, B>> pairs) { 093 List<B> snds = new ArrayList<>(pairs.size()); 094 for (Pair<A, B> pair : pairs) { 095 snds.add(pair.getSnd()); 096 } 097 return snds; 098 } 099 100 /** 101 * Returns the second element of the tuples in the same order. Equivalent to 102 * the Haskell code {@code map snd}. 103 * 104 * @param <A> the type of first element in the pairs 105 * @param <B> the type of second element in the pairs 106 * @param pairs the tuples 107 * @param array the array to write to if the size is correct 108 * @return the second element of the tuples 109 */ 110 @SafeVarargs 111 public static <A, B> B[] mapSnd(Pair<A, B>[] pairs, B... array) { 112 @SuppressWarnings("unchecked") 113 B[] to = array.length == pairs.length 114 ? array 115 : (B[]) Array.newInstance(array.getClass().getComponentType(), pairs.length); 116 for (int i = 0; i < to.length; i++) { 117 to[i] = pairs[i].getSnd(); 118 } 119 return to; 120 } 121 122 @Override 123 public boolean equals(Object obj) { 124 if (obj instanceof Pair<?, ?>) { 125 Pair<?, ?> other = (Pair<?, ?>) obj; 126 return fst.equals(other.fst) && snd.equals(other.snd); 127 } 128 return false; 129 } 130 131 @Override 132 public int hashCode() { 133 return fst.hashCode() ^ snd.hashCode(); 134 } 135 136 @Override 137 public String toString() { 138 return "(" + fst + ", " + snd + ")"; 139 } 140}