Created
February 14, 2013 12:45
-
-
Save jqno/4952526 to your computer and use it in GitHub Desktop.
My answer to Cedric Beust's coding challenge ("Light" edition)
http://beust.com/weblog/2013/02/13/coding-challenge-light-edition/
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
// My implementation of Cedric Beust's coding challenge: | |
// | |
// A School has either a name (“Stanford”) or a nickname (“UCSD”) or both. | |
// | |
// Your task is to write equals() and hashCode() methods for the School class | |
// that satisfy the following requirement: two Schools are identical if they | |
// either have the same name or the same nickname. | |
// | |
// http://beust.com/weblog/2013/02/13/coding-challenge-light-edition/ | |
import nl.jqno.equalsverifier.EqualsVerifier; | |
import org.junit.Test; | |
public class SchoolTest { | |
public static final class School { | |
private final String name; | |
private final String nickname; | |
public School(String name, String nickname) { | |
this.name = name; | |
this.nickname = nickname; | |
} | |
// OK, let's give this equals method a try. | |
@Override | |
public boolean equals(Object obj) { | |
if (!(obj instanceof School)) { | |
return false; | |
} | |
School other = (School)obj; | |
return nullSafeEqual(name, other.name) || | |
nullSafeEqual(nickname, other.nickname); | |
} | |
private boolean nullSafeEqual(String a, String b) { | |
return a == null ? b == null : a.equals(b); | |
} | |
@Override | |
public int hashCode() { | |
// Well, this *does* satisfy the hashCode contract, doesn't it :)? | |
return 42; | |
} | |
@Override | |
public String toString() { | |
return "School: name=" + name + ", nickname=" + nickname; | |
} | |
} | |
@Test | |
public void testEquals() { | |
// My alma mater: | |
School tue = new School("Technische Universiteit Eindhoven", "TU/e"); | |
// There's a university in my home town that famously changed its name: | |
School one = new School("Katholieke Universiteit Brabant", "KUB"); | |
School two = new School("Katholieke Universiteit Brabant", "UvT"); | |
School three = new School("Universiteit van Tilburg", "KUB"); | |
School four = new School("Universiteit van Tilburg", "UvT"); | |
// Using EqualsVerifier to check equality. | |
// Full disclosure: it's written by me. | |
// See http://code.google.com/p/equalsverifier/ | |
// It works for any pair of schools: | |
EqualsVerifier.forRelaxedEqualExamples(one, two) | |
.andUnequalExample(tue) | |
.verify(); | |
EqualsVerifier.forRelaxedEqualExamples(three, four) | |
.andUnequalExample(tue) | |
.verify(); | |
EqualsVerifier.forRelaxedEqualExamples(one, three) | |
.andUnequalExample(tue) | |
.verify(); | |
EqualsVerifier.forRelaxedEqualExamples(two, four) | |
.andUnequalExample(tue) | |
.verify(); | |
// But once you add a third school, it breaks down: | |
EqualsVerifier.forRelaxedEqualExamples(one, two, three) | |
.andUnequalExample(tue) | |
.verify(); | |
// And that makes sense, because the transitivity requirement cannot hold: | |
// * one equals two | |
// * two equals three | |
// * one does not equal three | |
// Therefore, there is no way to write this equals method, and still satisfy | |
// the requirements of the equals contract. | |
// P.S. If I'm wrong, please let me know, so I can update EqualsVerifier :). | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment