Java 流 distinct 不适用于自定义对象?

arm*_*ani 0 java java-stream

Javadocs说 distinct() - 返回一个由该流的不同元素(根据 Object.equals(Object))组成的流。

我有一个包含一些重复项的自定义对象列表。当我distinct()在流列表上运行方法时,我仍然得到原始列表。为什么即使我在自定义对象中定义了一个 equals 方法,也没有删除重复项?

代码 :

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<CustomType> data = Arrays.asList(
            new CustomType("a"),
            new CustomType("b"),
            new CustomType("a"),
            new CustomType("c")
        );

        List<CustomType> filtered = data.stream().distinct().collect(Collectors.toList());
        filtered.forEach(System.out::println);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出 :

[a]
[b]
[a]
[c]
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我在 CustomType.equals(arg) 中放置了一个断点,并注意到 distinct() 甚至没有调用 equals(arg)。

Hov*_*els 5

在覆盖 equals 时,您始终应该覆盖 hashCode,否则您的 equals 方法不符合预期的约定:

@Override
public int hashCode() {
    return data1.hashCode();
}
Run Code Online (Sandbox Code Playgroud)

这表明distinct() 首先使用hashCode 进行测试,然后如果hashCode 相同,则使用equals 方法。

  • @armani:每个对象都有一个 hashCode 方法,并且通常在 equals 之前调用它,因为它的计算成本比 equals 更低。如果hashCode值不相同,则无需调用更昂贵的equals方法。如果您不重写 hashCode,则将调用默认方法,该方法将为每个对象返回唯一的值。 (2认同)