提问者:小点点

在HashSet中插入对象的条件?


请耐心等待,因为我试图引入一个与许多活动线程直接矛盾的新概念。

在HashSet中插入对象的条件是什么?

查看源代码,它会关注:

if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

完整代码位于:HashSet.java

所以,这取决于

  1. 哈希码
  2. 等于()
  3. == 即如果它们是相同的对象。

看看条件4。尽管equals()返回false,但对象会被添加到HashSet。在所有其他情况下,当且仅当equals()返回false时,对象才会被添加。因此,可以说(忽略条件4),一个对象是否会添加到HashSet的决定只是由equals()方法做出的。当被问及为什么我们使用hashCode()时,标准答案是它通过简单地比较整数来提高性能,因为短路运算符保存了equals()方法的执行。这个论点在许多线程中讨论过,比如如果我们无论如何都要检查等于,为什么我们要检查哈希?

然而,我发现这个论点是不正确的。如果equals()返回false,==返回true,哈希码实际上有一个决定。这是极不可能的,因为同一个对象通常会为equals()返回true,除非有人明确地(违反了equals)约定)重写equals方法,以便它为同一对象返回不同的值。尽管如此,这是一种可能性,java似乎正在为某些违约代码提供风险管理。你来吧!


共3个答案

匿名用户

HashSet 要求传递给它的对象遵守 hashCode 的约定并等于 — 如果它们不这样做,那么垃圾输入垃圾。等于的协定规定,如果两个引用是 ==,则它们必须相等。因此,上面的条件 4 违反了相等契约,因此违反了 HashSet 的契约,因此 HashSet 在提出这样一组条件时没有义务采取有意义的行动。

条件5也会破坏合同。

匿名用户

如果两个引用相等或相同(==),那么< code>equals()应该返回true。

如果equals()方法为两个对象返回true,那么hashCode()也需要为这两个对象返回相同的哈希值。

因此,让我们考虑8个场景的真值表,如下所示,只有4个有效场景。

| hashCode() | equals() |   ==   | add() |
| not-same   | false    | false  | true  |
| not-same   | false    | true   |   -   | - INVALID scenario (== vs equals)
| not-same   | true     | false  |   -   | - INVALID scenario (hash vs equals)
| not-same   | true     | true   |   -   | - INVALID scenario (hash vs equals)
| same       | false    | false  | true  |
| same       | false    | true   |   -   | - INVALID scenario (== vs equals)
| same       | true     | false  | false | 
| same       | true     | true   | false |

在问题表中;S. No 4

匿名用户

if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

e.hash == 出于效率原因,哈希在这种情况下存在,它是(在理智的情况下)执行的最快的测试,用于在第一个障碍时打折相等性。在程序处于有效状态的所有情况下(不违反 == .equals() .hashCode() 合约),它对 if 语句的最终结果没有逻辑影响。

由于破坏==. equals(). hashCode()契约而导致的条件不被考虑,因为这样的程序处于无效状态并且没有定义行为。违反契约下的效果可能会从实施变为实施,因此永远不应该依赖。