java - 了解哈希集

标签 java set hashset

这是我的问题,“HashSet 对象”可以有重复的元素吗?

如果我阅读 Set Interface 定义,我会看到:

A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element. As implied by its name, this interface models the mathematical set abstraction.

现在我们要编写一个简单的示例:

定义A类:

public class A {

    @Override
    public boolean equals(Object obj) {
        return true;
    }

}

现在执行这段代码;

Set<A> set = new HashSet<A>();
set.add(new A());
set.add(new A());
System.out.println(set.toString());

这就是结果:

[com.maths.graphs.A@b9e9a3, com.maths.graphs.A@18806f7]

为什么像 HashSet 这样实现 Set 接口(interface)的类会包含重复的元素?

谢谢!!

最佳答案

您已经破坏了 equals-hashcode 契约。

如果您重写 equals 方法,则还必须重写 hashCode() 方法,以便:

Two objects which are equal give the same hash, and preferably unequal objects are highly likely to give different hashcodes

这很重要,因为许多对象(不出所料,包括 HashSet)使用哈希码作为快速、有效的早期步骤来消除不相等的对象。这就是这里发生的情况,因为不同 A 的哈希码会有所不同,因为它们仍然使用 object< 中提供的 .hashCode() 实现.

如果您要按如下方式创建 A 类,则集合中不允许有超过 1 个 A

public class A {

    @Override
    public boolean equals(Object obj) {
        return true;
    }

    @Override
    public int hashCode() {
        int hash = 1; //any number since in this case all objects of class A are equal to everything
        return hash;
    }

}

来自 javadoc

public int hashCode()

Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by HashMap.

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

如果您在重写 equals 方法时不包含重写的 HashCode 方法,大多数 IDE 都会反对,并且可以为您生成 hashCode 方法。

注释

严格来说,我的 hashCode() 方法并不完全满足契约(Contract)。由于 A#equals(Object obj) 等于任何东西,包括不属于 A 类型的对象,因此不可能完全满足契约。理想情况下, equals 方法也应更改为以下内容以覆盖所有基础

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof A){
           return true;
        }else{
           return false;
        }
    }

关于java - 了解哈希集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23563798/

相关文章:

java - MavenCli 输出到 eclipse/maven 控制台

SQL 计算重叠集的不同元素

Java所有确定元素在列表中都相同

java - java中如何比较两个哈希集?

java - Thymeleaf 3 和 Spring Boot 2.1 的模板解析错误

java - 用公式 N^R 的所有组合填充数组

c++ - 如何在没有临时设置的情况下将设置差异 s1-s2 存储在 s1 中?

sql - 关系型数据库查询问题

c# - 避免在数据库中添加重复项的最佳方法

Java - 谷歌地图 API - 两个地址之间的距离