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 3-tuple. 010 * 011 * 012 * @param <A> the type of fst 013 * @param <B> the type of snd 014 * @param <C> the type of thd 015 * @author jimmy 016 */ 017public class Triple<A, B, C> { 018 019 private final A fst; 020 private final B snd; 021 private final C thd; 022 023 public Triple(A fst, B snd, C thd) { 024 this.fst = Check.notNull(fst); 025 this.snd = Check.notNull(snd); 026 this.thd = Check.notNull(thd); 027 } 028 029 public Triple(Pair<? extends A, ? extends B> pair, C thd) { 030 this(pair.getFst(), pair.getSnd(), thd); 031 } 032 033 public Triple(A fst, Pair<? extends B, ? extends C> pair) { 034 this(fst, pair.getFst(), pair.getSnd()); 035 } 036 037 public Triple(Triple<? extends A, ? extends B, ? extends C> triple) { 038 this(triple.getFst(), triple.getSnd(), triple.getThd()); 039 } 040 041 public A getFst() { 042 return fst; 043 } 044 045 public B getSnd() { 046 return snd; 047 } 048 049 public C getThd() { 050 return thd; 051 } 052 053 public Pair<A, B> getFstSnd() { 054 return new Pair<>(fst, snd); 055 } 056 057 public Pair<B, C> getSndThd() { 058 return new Pair<>(snd, thd); 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 <C> the type of third element in the pairs 068 * @param triples the tuples 069 * @return the first element of the tuples 070 */ 071 public static <A, B, C> List<A> mapFst(List<Triple<A, B, C>> triples) { 072 List<A> fsts = new ArrayList<>(triples.size()); 073 for (Triple<A, B, C> triple : triples) { 074 fsts.add(triple.getFst()); 075 } 076 return fsts; 077 } 078 079 /** 080 * Returns the first element of the tuples in the same order. Equivalent to 081 * the Haskell code {@code map fst}. 082 * 083 * @param <A> the type of first element in the pairs 084 * @param <B> the type of second element in the pairs 085 * @param <C> the type of third element in the pairs 086 * @param triples the tuples 087 * @param array the array to write to if the size is correct 088 * @return the first element of the tuples 089 */ 090 @SafeVarargs 091 public static <A, B, C> A[] mapFst(Triple<A, B, C>[] triples, A... array) { 092 @SuppressWarnings("unchecked") 093 A[] to = array.length == triples.length 094 ? array 095 : (A[]) Array.newInstance(array.getClass().getComponentType(), triples.length); 096 for (int i = 0; i < to.length; i++) { 097 to[i] = triples[i].getFst(); 098 } 099 return to; 100 } 101 102 /** 103 * Returns the second element of the tuples in the same order. Equivalent to 104 * the Haskell code {@code map snd}. 105 * 106 * @param <A> the type of first element in the pairs 107 * @param <B> the type of second element in the pairs 108 * @param <C> the type of third element in the pairs 109 * @param triples the tuples 110 * @return the second element of the tuples 111 */ 112 public static <A, B, C> List<B> mapSnd(List<Triple<A, B, C>> triples) { 113 List<B> snds = new ArrayList<>(triples.size()); 114 for (Triple<A, B, C> triple : triples) { 115 snds.add(triple.getSnd()); 116 } 117 return snds; 118 } 119 120 /** 121 * Returns the second element of the tuples in the same order. Equivalent to 122 * the Haskell code {@code map snd}. 123 * 124 * @param <A> the type of first element in the pairs 125 * @param <B> the type of second element in the pairs 126 * @param <C> the type of third element in the pairs 127 * @param triples the tuples 128 * @param array the array to write to if the size is correct 129 * @return the second element of the tuples 130 */ 131 @SafeVarargs 132 public static <A, B, C> B[] mapSnd(Triple<A, B, C>[] triples, B... array) { 133 @SuppressWarnings("unchecked") 134 B[] to = array.length == triples.length 135 ? array 136 : (B[]) Array.newInstance(array.getClass().getComponentType(), triples.length); 137 for (int i = 0; i < to.length; i++) { 138 to[i] = triples[i].getSnd(); 139 } 140 return to; 141 } 142 143 /** 144 * Returns the third element of the tuples in the same order. Equivalent to 145 * the Haskell code {@code map thd}. 146 * 147 * @param <A> the type of first element in the pairs 148 * @param <B> the type of second element in the pairs 149 * @param <C> the type of third element in the pairs 150 * @param triples the tuples 151 * @return the third element of the tuples 152 */ 153 public static <A, B, C> List<C> mapThd(List<Triple<A, B, C>> triples) { 154 List<C> thds = new ArrayList<>(triples.size()); 155 for (Triple<A, B, C> triple : triples) { 156 thds.add(triple.getThd()); 157 } 158 return thds; 159 } 160 161 /** 162 * Returns the third element of the tuples in the same order. Equivalent to 163 * the Haskell code {@code map thd}. 164 * 165 * @param <A> the type of first element in the pairs 166 * @param <B> the type of second element in the pairs 167 * @param <C> the type of third element in the pairs 168 * @param triples the tuples 169 * @param array the array to write to if the size is correct 170 * @return the third element of the tuples 171 */ 172 @SafeVarargs 173 public static <A, B, C> C[] mapThd(Triple<A, B, C>[] triples, C... array) { 174 @SuppressWarnings("unchecked") 175 C[] to = array.length == triples.length 176 ? array 177 : (C[]) Array.newInstance(array.getClass().getComponentType(), triples.length); 178 for (int i = 0; i < to.length; i++) { 179 to[i] = triples[i].getThd(); 180 } 181 return to; 182 } 183 184 @Override 185 public boolean equals(Object obj) { 186 if (obj instanceof Triple<?, ?, ?>) { 187 Triple<?, ?, ?> other = (Triple<?, ?, ?>) obj; 188 return fst.equals(other.fst) && snd.equals(other.snd) && thd.equals(other.thd); 189 } 190 return false; 191 } 192 193 @Override 194 public int hashCode() { 195 return fst.hashCode() ^ snd.hashCode() ^ thd.hashCode(); 196 } 197 198 @Override 199 public String toString() { 200 return "(" + fst + ", " + snd + ", " + thd + ")"; 201 } 202}