Skip to content

Commit 26a6cd6

Browse files
authored
Merge pull request eugenp#5733 from cror/equals-hashcode
BAEL-2388: examples for equals and hashCode
2 parents 3d2f6ef + a67c10e commit 26a6cd6

8 files changed

Lines changed: 270 additions & 0 deletions

File tree

core-java-lang/pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@
6666
<artifactId>mail</artifactId>
6767
<version>${javax.mail.version}</version>
6868
</dependency>
69+
<dependency>
70+
<groupId>nl.jqno.equalsverifier</groupId>
71+
<artifactId>equalsverifier</artifactId>
72+
<version>${equalsverifier.version}</version>
73+
<scope>test</scope>
74+
</dependency>
6975
</dependencies>
7076

7177
<build>
@@ -424,6 +430,7 @@
424430
<maven-shade-plugin.version>3.1.1</maven-shade-plugin.version>
425431
<spring-boot-maven-plugin.version>2.0.3.RELEASE</spring-boot-maven-plugin.version>
426432
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
433+
<equalsverifier.version>3.0.3</equalsverifier.version>
427434
</properties>
428435

429436
</project>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.baeldung.equalshashcode;
2+
3+
class Money {
4+
5+
int amount;
6+
String currencyCode;
7+
8+
Money(int amount, String currencyCode) {
9+
this.amount = amount;
10+
this.currencyCode = currencyCode;
11+
}
12+
13+
@Override
14+
public boolean equals(Object o) {
15+
if (o == this)
16+
return true;
17+
if (!(o instanceof Money))
18+
return false;
19+
Money other = (Money)o;
20+
boolean currencyCodeEquals = (this.currencyCode == null && other.currencyCode == null)
21+
|| (this.currencyCode != null && this.currencyCode.equals(other.currencyCode));
22+
return this.amount == other.amount
23+
&& currencyCodeEquals;
24+
}
25+
26+
@Override
27+
public int hashCode() {
28+
int result = 17;
29+
result = 31 * result + amount;
30+
if (currencyCode != null) {
31+
result = 31 * result + currencyCode.hashCode();
32+
}
33+
return result;
34+
}
35+
36+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.baeldung.equalshashcode;
2+
3+
class Team {
4+
5+
final String city;
6+
final String department;
7+
8+
Team(String city, String department) {
9+
this.city = city;
10+
this.department = department;
11+
}
12+
13+
@Override
14+
public final boolean equals(Object o) {
15+
if (o == this)
16+
return true;
17+
if (!(o instanceof Team))
18+
return false;
19+
Team otherTeam = (Team)o;
20+
boolean cityEquals = (this.city == null && otherTeam.city == null)
21+
|| this.city != null && this.city.equals(otherTeam.city);
22+
boolean departmentEquals = (this.department == null && otherTeam.department == null)
23+
|| this.department != null && this.department.equals(otherTeam.department);
24+
return cityEquals && departmentEquals;
25+
}
26+
27+
@Override
28+
public final int hashCode() {
29+
int result = 17;
30+
if (city != null) {
31+
result = 31 * result + city.hashCode();
32+
}
33+
if (department != null) {
34+
result = 31 * result + department.hashCode();
35+
}
36+
return result;
37+
}
38+
39+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.baeldung.equalshashcode;
2+
3+
class Voucher {
4+
5+
private Money value;
6+
private String store;
7+
8+
Voucher(int amount, String currencyCode, String store) {
9+
this.value = new Money(amount, currencyCode);
10+
this.store = store;
11+
}
12+
13+
@Override
14+
public boolean equals(Object o) {
15+
if (o == this)
16+
return true;
17+
if (!(o instanceof Voucher))
18+
return false;
19+
Voucher other = (Voucher)o;
20+
boolean valueEquals = (this.value == null && other.value == null)
21+
|| (this.value != null && this.value.equals(other.value));
22+
boolean storeEquals = (this.store == null && other.store == null)
23+
|| (this.store != null && this.store.equals(other.store));
24+
return valueEquals && storeEquals;
25+
}
26+
27+
@Override
28+
public int hashCode() {
29+
int result = 17;
30+
if (this.value != null) {
31+
result = 31 * result + value.hashCode();
32+
}
33+
if (this.store != null) {
34+
result = 31 * result + store.hashCode();
35+
}
36+
return result;
37+
}
38+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.baeldung.equalshashcode;
2+
3+
/* (non-Javadoc)
4+
* This class overrides equals, but it doesn't override hashCode.
5+
*
6+
* To see which problems this leads to:
7+
* TeamUnitTest.givenMapKeyWithoutHashCode_whenSearched_thenReturnsWrongValue
8+
*/
9+
class WrongTeam {
10+
11+
String city;
12+
String department;
13+
14+
WrongTeam(String city, String department) {
15+
this.city = city;
16+
this.department = department;
17+
}
18+
19+
@Override
20+
public boolean equals(Object o) {
21+
if (o == this)
22+
return true;
23+
if (!(o instanceof WrongTeam))
24+
return false;
25+
WrongTeam otherTeam = (WrongTeam)o;
26+
return this.city == otherTeam.city
27+
&& this.department == otherTeam.department;
28+
}
29+
30+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.baeldung.equalshashcode;
2+
3+
/* (non-Javadoc)
4+
* This class extends the Money class that has overridden the equals method and once again overrides the equals method.
5+
*
6+
* To see which problems this leads to:
7+
* MoneyUnitTest.givenMoneyAndVoucherInstances_whenEquals_thenReturnValuesArentSymmetric
8+
*/
9+
class WrongVoucher extends Money {
10+
11+
private String store;
12+
13+
WrongVoucher(int amount, String currencyCode, String store) {
14+
super(amount, currencyCode);
15+
16+
this.store = store;
17+
}
18+
19+
@Override
20+
public boolean equals(Object o) {
21+
if (o == this)
22+
return true;
23+
if (!(o instanceof WrongVoucher))
24+
return false;
25+
WrongVoucher other = (WrongVoucher)o;
26+
boolean currencyCodeEquals = (this.currencyCode == null && other.currencyCode == null)
27+
|| (this.currencyCode != null && this.currencyCode.equals(other.currencyCode));
28+
boolean storeEquals = (this.store == null && other.store == null)
29+
|| (this.store != null && this.store.equals(other.store));
30+
return this.amount == other.amount
31+
&& currencyCodeEquals
32+
&& storeEquals;
33+
}
34+
35+
@Override
36+
public int hashCode() {
37+
int result = 17;
38+
result = 31 * result + amount;
39+
if (this.currencyCode != null) {
40+
result = 31 * result + currencyCode.hashCode();
41+
}
42+
if (this.store != null) {
43+
result = 31 * result + store.hashCode();
44+
}
45+
return result;
46+
}
47+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.baeldung.equalshashcode;
2+
3+
import static org.junit.Assert.assertTrue;
4+
import static org.junit.Assert.assertFalse;
5+
6+
import org.junit.Test;
7+
8+
public class MoneyUnitTest {
9+
10+
@Test
11+
public void givenMoneyInstancesWithSameAmountAndCurrency_whenEquals_thenReturnsTrue() {
12+
Money income = new Money(55, "USD");
13+
Money expenses = new Money(55, "USD");
14+
15+
assertTrue(income.equals(expenses));
16+
}
17+
18+
@Test
19+
public void givenMoneyAndVoucherInstances_whenEquals_thenReturnValuesArentSymmetric() {
20+
Money cash = new Money(42, "USD");
21+
WrongVoucher voucher = new WrongVoucher(42, "USD", "Amazon");
22+
23+
assertFalse(voucher.equals(cash));
24+
assertTrue(cash.equals(voucher));
25+
}
26+
27+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.baeldung.equalshashcode;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertFalse;
5+
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
9+
import org.junit.Test;
10+
11+
import nl.jqno.equalsverifier.EqualsVerifier;
12+
13+
public class TeamUnitTest {
14+
15+
@Test
16+
public void givenMapKeyWithHashCode_whenSearched_thenReturnsCorrectValue() {
17+
Map<Team,String> leaders = new HashMap<>();
18+
leaders.put(new Team("New York", "development"), "Anne");
19+
leaders.put(new Team("Boston", "development"), "Brian");
20+
leaders.put(new Team("Boston", "marketing"), "Charlie");
21+
22+
Team myTeam = new Team("New York", "development");
23+
String myTeamleader = leaders.get(myTeam);
24+
25+
assertEquals("Anne", myTeamleader);
26+
}
27+
28+
@Test
29+
public void givenMapKeyWithoutHashCode_whenSearched_thenReturnsWrongValue() {
30+
Map<WrongTeam,String> leaders = new HashMap<>();
31+
leaders.put(new WrongTeam("New York", "development"), "Anne");
32+
leaders.put(new WrongTeam("Boston", "development"), "Brian");
33+
leaders.put(new WrongTeam("Boston", "marketing"), "Charlie");
34+
35+
WrongTeam myTeam = new WrongTeam("New York", "development");
36+
String myTeamleader = leaders.get(myTeam);
37+
38+
assertFalse("Anne".equals(myTeamleader));
39+
}
40+
41+
@Test
42+
public void equalsContract() {
43+
EqualsVerifier.forClass(Team.class).verify();
44+
}
45+
46+
}

0 commit comments

Comments
 (0)