在HashSet中包含相等的对象

3

你好,我发现一个和集合相关的问题。

public class Person {
    private String name;

    public Person(String name){
        this.name=name;
    }

    public boolean equals(Object o){
        if(!(o instanceof Person))return false;
        Person p=(Person)o;
        return p.name.equals(this.name);
    }

    public static void main(String[] args) {
        HashSet<Person> hs=new HashSet<Person>();
        hs.add(new Person("Hi"));
        hs.add(new Person("Hi"));
        hs.add(new Person("Hi"));
        hs.add(new Person("Hi"));

        System.out.println("Elements"+hs.size());
    }
}

Hashset的大小为4,但它不应该是1吗?因为equals方法已经实现了,HashSet是否可以包含具有相同名称的多个Person对象?

由于hashCode方法没有被覆盖,所有的Person对象的哈希码都相同吗?

1个回答

5

.equals()是不够的。你需要使用.hashCode()

当你实现其中一个时,通常情况下,总是要实现另一个!

并且遵守契约;特别是,两个同一类的实例,如果使用.equals()则必须具有相同的.hashCode()


现在,一个HashSet,正如其名称所示,依赖于…哈希值。 在这种情况下,取决于.hashCode()的结果。根据结果,它将对象插入到不同的哈希桶中。

由于您的对象都具有不同的哈希码,因此它们最终会分别落在四个不同的桶中…


1
谢谢。如果没有实现.hashCode()方法,那么在这种情况下是什么确定了哈希值的不同值来区分对象?当我们只添加一个元素时,hs.add(4); 对于两倍大小的HashSet来说显示为1。这与以前的情况有何不同? - user2445123
1
简短回答,Object.hashCode() 部分说明了 通常通过将对象的内部地址转换为整数来实现 - Elliott Frisch
2
如果您想查看对象x的默认哈希代码,则可以调用System.identityHashCode(x)。当您添加hs.add(4)时,您正在添加具有始终哈希码4(等于其值)的数字4。在Person的情况下,您每次都创建新的Person对象,在内存中具有不同的地址,因此具有不同的哈希代码。 - Wickoo
好的,谢谢。我还有一个问题。如果一个 HashSet 包含多个名称为“Fred”的 Person 对象,那么删除另一个同名的 Person 对象也将把它们全部删除。这有什么问题吗? - user2445123
@Hiru,你的理解是错误的,因为第二个“Fred”根本不会被添加; 集合会丢弃重复项。前提是在使用HashSet时,您已经正确编码了equals()/ hashCode();) - fge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接