Created
November 28, 2014 22:40
-
-
Save kkleidal/af3ef3d7e73105a36412 to your computer and use it in GitHub Desktop.
Java Pair class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package util; | |
/** | |
* Creates a pair of two objects | |
* | |
* @param <T1> the type of object 1 | |
* @param <T2> the type of object 2 | |
*/ | |
public class Pair<T1, T2> { | |
/** | |
* The first object | |
*/ | |
private final T1 obj1; | |
/** | |
* The second object | |
*/ | |
private final T2 obj2; | |
/** | |
* Creates a new pair of objects | |
* | |
* @param first the first object | |
* @param second the second object | |
*/ | |
public Pair(T1 first, T2 second) { | |
this.obj1 = first; | |
this.obj2 = second; | |
} | |
/** | |
* @return the first object | |
*/ | |
public T1 getFirst() { | |
return this.obj1; | |
} | |
/** | |
* @return the second object | |
*/ | |
public T2 getSecond() { | |
return this.obj2; | |
} | |
@Override | |
public boolean equals(Object other) { | |
if (!(other instanceof Pair<?,?>)) { | |
return false; | |
} | |
Pair<?,?> otherObj = (Pair<?,?>)other; | |
return otherObj.obj1.equals(obj1) && otherObj.obj2.equals(obj2); | |
} | |
/** | |
* The number of bits per bytes | |
*/ | |
private static final int BITS_PER_BYTES = 8; | |
/** | |
* The number of bytes in the hash | |
*/ | |
private static final int NUMBER_BITS = Integer.BYTES * BITS_PER_BYTES; | |
/** | |
* The number of bytes in the hash | |
*/ | |
private static final int HALF_NUMBER_BITS = NUMBER_BITS / 2; | |
/** | |
* 0's for the first half of the int, 1's for the second half of the int | |
*/ | |
private static final int EMPTY_FULL = (1 << (HALF_NUMBER_BITS + 1)) - 1; | |
/** | |
* 1's for the first half of the int, 0's for the second half of the int | |
*/ | |
private static final int FULL_EMPTY = EMPTY_FULL << HALF_NUMBER_BITS; | |
@Override | |
public int hashCode() { | |
int firstHash = this.obj1.hashCode(); | |
int first16Bits = (EMPTY_FULL & firstHash) ^ ((FULL_EMPTY & firstHash) >> HALF_NUMBER_BITS); | |
int secondHash = this.obj2.hashCode(); | |
int second16Bits = (EMPTY_FULL & secondHash) ^ ((FULL_EMPTY & secondHash) >> HALF_NUMBER_BITS); | |
return (first16Bits << HALF_NUMBER_BITS) | second16Bits; | |
} | |
@Override | |
public String toString() { | |
return String.format("Pair<%s, %s>", this.obj1.toString(), | |
this.obj2.toString()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package util; | |
import static org.junit.Assert.assertEquals; | |
import static org.junit.Assert.assertFalse; | |
import static org.junit.Assert.assertTrue; | |
import org.junit.*; | |
/** | |
* Tests for the Pair class | |
*/ | |
public class PairTest { | |
/* | |
* Testing strategy | |
* | |
* - creation | |
* - access to elements | |
* - nested pairs | |
* - equality/hash code | |
* - equal object | |
* - non-equal objects | |
*/ | |
/** | |
* Tests creation of basic pair | |
*/ | |
@Test | |
public void pairCreation() { | |
Pair<Integer, String> examplePair = | |
new Pair<Integer, String>(42, "the answer to life the universe and everything"); | |
assertEquals(42, examplePair.getFirst().intValue()); | |
assertEquals("the answer to life the universe and everything", examplePair.getSecond()); | |
} | |
/** | |
* Tests creation of nested pair | |
*/ | |
@Test | |
public void nestedPirCreation() { | |
Pair<Integer, Pair<String, String>> nestedPair = | |
new Pair<Integer, Pair<String, String>>(42, new Pair<String, String>("the answer to life", "the universe and everything")); | |
assertEquals(42, nestedPair.getFirst().intValue()); | |
assertEquals("the answer to life", nestedPair.getSecond().getFirst()); | |
assertEquals("the universe and everything", nestedPair.getSecond().getSecond()); | |
} | |
/** | |
* Tests equality and hashing for two equal objects | |
*/ | |
@Test | |
public void equalityEqual() { | |
Pair<Integer, Pair<String, String>> nestedPair1 = | |
new Pair<Integer, Pair<String, String>>(42, new Pair<String, String>("the answer to life", "the universe and everything")); | |
Pair<Integer, Pair<String, String>> nestedPair2 = | |
new Pair<Integer, Pair<String, String>>(42, new Pair<String, String>("the answer to life", "the universe and everything")); | |
assertTrue(nestedPair1.equals(nestedPair2)); | |
assertTrue(nestedPair2.equals(nestedPair1)); | |
assertTrue(nestedPair1.hashCode() == nestedPair2.hashCode()); | |
} | |
/** | |
* Tests equality and hashing for two inequal objects | |
*/ | |
@Test | |
public void equalityInequal() { | |
Pair<Integer, Pair<String, String>> nestedPair1 = | |
new Pair<Integer, Pair<String, String>>(42, new Pair<String, String>("the answer to life", "the universe and everything")); | |
Pair<Integer, Pair<String, String>> nestedPair2 = | |
new Pair<Integer, Pair<String, String>>(42, new Pair<String, String>("the answer to life", "he universe and everything")); | |
assertFalse(nestedPair1.equals(nestedPair2)); | |
assertFalse(nestedPair2.equals(nestedPair1)); | |
if (nestedPair1.hashCode() == nestedPair2.hashCode()) { | |
System.err.println("Warning: hash collision between " + nestedPair1.toString() + " and " + nestedPair2.toString()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment