Duplicate HashSet entries with original class
Koji Saiki
Posted on May 6, 2021
TL;DR
You should implement both of hashCode
and equals
for using in HashSet.
Env
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_265-b01)
OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.265-b01, mixed mode)
Try
Below MyModel class is my sample class with some properties and provide same hashcode with same property values.
However equals
returns false.
public class MyModel {
private String name;
private int age;
public MyModel(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
return false;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
import org.junit.Test;
import java.util.HashSet;
import static org.junit.Assert.*;
public class MyModelTest {
@Test
public void testHashSet() {
HashSet<MyModel> set = new HashSet<>();
// Add models with same property values.
set.add(new MyModel("taro", 10));
set.add(new MyModel("taro", 10));
// We want the set has only 1 entry.
assertEquals(1, set.size());
}
}
But, you will see the result as below.
java.lang.AssertionError:
Expected :1
Actual :2
For pass the assertion, you should implement equals
also.
public class MyModel {
private String name;
private int age;
public MyModel(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyModel myModel = (MyModel) o;
if (age != myModel.age) return false;
return name != null ? name.equals(myModel.name) : myModel.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
Why
In OpenJDK, HashSet depends on HashMap implementation.
- HashSet::add
https://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/classes/java/util/HashSet.java#L219
- HashMap::putVal
https://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/classes/java/util/HashMap.java#L633-L634
💖 💪 🙅 🚩
Koji Saiki
Posted on May 6, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.