Javadocs say that distinct() - Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.
I have a list of custom objects with some duplicates. When I run distinct() method on the streamed list, I still get the original list back. Why are the duplicates not getting removed even though I defined an equals method in the custom object ?
Code :
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
class CustomType {
private String data1;
public CustomType(String data1) { this.data1 = data1; }
public String getData1() { return data1; }
@Override
public boolean equals(Object other){
CustomType otherC = (CustomType) other;
return this.getData1().equals(otherC.getData1());
}
@Override
public String toString(){
return "[" + data1 + "]";
}
}
public class StreamDistinctTest {
public static void main(String [] args){
List data = Arrays.asList(
new CustomType("a"),
new CustomType("b"),
new CustomType("a"),
new CustomType("c")
);
List filtered = data.stream().distinct().collect(Collectors.toList());
filtered.forEach(System.out::println);
}
}
Output :
[a]
[b]
[a]
[c]
BTW, I put a breakpoint in CustomType.equals(arg) and noticed that distinct( ) does not even call equals(arg).
解决方案
You always should override hashCode when overriding equals, else your equals method doesn't obey the expected contract:
@Override
public int hashCode() {
return data1.hashCode();
}
This works suggesting that distinct() first tests using hashCode and then if hashCodes are the same, uses the equals method.