Java hashCode疑问

发布于 2024-10-31 20:32:12 字数 930 浏览 2 评论 0原文

我有这个程序:

import java.util.*;
public class test {
    private String s;
    public test(String s) { this.s = s; }
    public static void main(String[] args) {
        HashSet<Object> hs = new HashSet<Object>();
        test ws1 = new test("foo");
        test ws2 = new test("foo");
        String s1 = new String("foo");
        String s2 = new String("foo");
        hs.add(ws1); 
        hs.add(ws2); 
        hs.add(s1); 
        hs.add(s2); // removing this line also gives same output.
        System.out.println(hs.size()); 
    } 
}

请注意,这不是作业。今天早些时候,我们在测验中被问到这个问题。我知道答案,但试图理解为什么会这样。

上面的程序给出 3 作为输出。

谁能解释一下这是为什么吗?

我认为(不确定):

java.lang.String类覆盖了java.lang.Object中的hashCode方法。因此,值为“foo”的 String 对象将被视为重复项。测试类不会重写 hashCode 方法,最终使用 java.lang.Object 版本,并且该版本始终为每个对象返回不同的哈希码,因此这两个测试添加的对象被视为不同的。

I have this program:

import java.util.*;
public class test {
    private String s;
    public test(String s) { this.s = s; }
    public static void main(String[] args) {
        HashSet<Object> hs = new HashSet<Object>();
        test ws1 = new test("foo");
        test ws2 = new test("foo");
        String s1 = new String("foo");
        String s2 = new String("foo");
        hs.add(ws1); 
        hs.add(ws2); 
        hs.add(s1); 
        hs.add(s2); // removing this line also gives same output.
        System.out.println(hs.size()); 
    } 
}

Note that this is not a homework. We were asked this question on our quiz earlier today. I know the answers but trying to understand why it is so.

The above program gives 3 as output.

Can anyone please explain why that is?

I think (not sure):

The java.lang.String class overrides the hashCode method from java.lang.Object. So the String objects with value "foo" will be treated as duplicates. The test class does not override the hashCode method and ends up using the java.lang.Object version and this version always returns a different hashcode for every object, so the two test objects being added are treated as different.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

二智少女 2024-11-07 20:32:12

在本例中,它与 hashCode() 无关,而是与 equals() 方法有关。 HashSet仍然是Set,它具有不允许重复的语义。使用 equals() 方法检查重复项,如果是字符串,将返回 true

但是对于您的 testequals()< /code> 方法未定义,它将使用 Object 的默认实现,仅当两个引用都指向同一实例时才会返回 true。

方法 hashCode() 不是用来检查对象是否应该被视为相同,而是作为一种基于哈希函数将它们分布在集合中的方法。对于两个对象,此方法完全有可能返回相同的值,而 equals() 则返回 false。

PS ObjecthashCode 实现不保证值的唯一性。使用简单的循环很容易检查。

In this case it's not about hashCode() but is about equals() method. HashSet is still Set, which has semantic of not allowing duplicates. Duplicates are checked for using equals() method which in case of String will return true

However for your test class equals() method is not defined and it will use the default implementation from Object which will return true only when both references are to the same instance.

Method hashCode() is used not to check if objects should be treated as same but as a way to distribute them in collections based on hash functions. It's absolutely possible that for two objects this method will return same value while equals() will return false.

P.S. hashCode implementation of Object doesn't guarantee uniqueness of values. It's easy to check using simple loop.

滴情不沾 2024-11-07 20:32:12

哈希码用于缩小搜索结果范围。当我们尝试在 HashMap 中插入任何键时,它首先检查是否存在具有相同哈希码的任何其他对象,如果是,则检查 equals() 方法。如果两个对象相同,则 HashMap 将不会添加该键,而是会用新值替换旧值。

Hashcode is used to narrow down the search result. When we try to insert any key in HashMap first it checks whether any other object present with same hashcode and if yes then it checks for the equals() method. If two objects are same then HashMap will not add that key instead it will replace the old value by new one.

二智少女 2024-11-07 20:32:12

事实上,它不是关于重写hashcode(),而是关于equals方法。 Set 不允许重复。重复对象是对象在逻辑上相等的对象。

为了验证,您可以尝试使用“

System.out.println(ws1.equals(ws2));
System.out.println(s1.equals(s2));

如果对象相等,则一组只会接受一个”。

In fact, it is not about overriding the hashcode(), it is about equals method. Set does not allow duplicates. A duplicate is the one where the objects are logically equal.

For verifying you can try with

System.out.println(ws1.equals(ws2));
System.out.println(s1.equals(s2));

If the objects are equal, only one will be accepted by a set.

糖果控 2024-11-07 20:32:12

下面是一些(相当多)项目符号,重新定义了我为 SCJP 所做的准备工作中的 equals 和 hashcode。
希望它有帮助:

  • equals()、hashCode() 和 toString() 是公共的。
  • 重写 toString() 以便 System.out.println() 或其他方法可以看到有用的内容,例如对象的状态。
  • 使用 == 来确定两个引用变量是否引用同一个对象。
  • 使用 equals() 确定两个对象是否有意义等价。
  • 如果您不重写 equals(),您的对象将不会成为有用的散列键。
  • 如果不重写 equals(),则不同的对象不能被视为相等。
  • 字符串和包装器重写 equals() 并形成良好的散列键。
  • 当重写 equals() 时,使用 instanceof 运算符来确保您正在评估适当的类。
  • 当重写 equals() 时,比较对象的重要属性。
  • equals() 合约的亮点

    a.自反:x.equals(x) 为真。

    b.对称:如果 x.equals(y) 为 true,则 y.equals(x) 也一定为 true。

    c.传递性:如果 x.equals(y) 为 true,且 y.equals(z) 为 true,则 z.equals(x) 为 true。

    D.一致:多次调用 x.equals(y) 将返回相同的结果。

    e. Null:如果 x 不为 null,则 x.equals(null) 为 false。

    f.如果 x.equals(y) 为 true,则 x.hashCode() == y.hashCode() 为 true。
  • 如果重写 equals(),请重写 hashCode()。
  • HashMap、HashSet、Hashtable、LinkedHashMap 和 & LinkedHashSet 使用哈希。
  • 适当的 hashCode() 重写遵循 hashCode() 契约。
  • 有效的 hashCode() 重写可在其存储桶中均匀分配键。
  • 重写的 equals() 必须至少与其 hashCode() 配对一样精确。
  • 重申一下:如果两个对象相等,它们的哈希码也必须相等。
  • hashCode() 方法为所有实例返回相同的值是合法的(尽管实际上效率非常低)。

此外,如果您实现 equals 和 hashcode,则必须正确处理瞬态字段(如果有)。

Commons 对 EqualsBuilder 和 HashcodeBuilder 有很好的实现。它们可在 Coomons Lang 中找到
http://commons.apache.org/lang/

当我需要实现 equals 时我使用它们和哈希码。

Below are few (well quite many) bullets refarding the equals and hashcode from my preparations to SCJP.
Hope it helps:

  • equals(), hashCode(), and toString() are public.
  • Override toString() so that System.out.println() or other methods can see something useful, like your object's state.
  • Use == to determine if two reference variables refer to the same object.
  • Use equals() to determine if two objects are meaningfully equivalent.
  • If you don't override equals(), your objects won't be useful hashing keys.
  • If you don't override equals(), different objects can't be considered equal.
  • Strings and wrappers override equals() and make good hashing keys.
  • When overriding equals(), use the instanceof operator to be sure you're evaluating an appropriate class.
  • When overriding equals(), compare the objects' significant attributes.
  • Highlights of the equals() contract:

    a. Reflexive: x.equals(x) is true.

    b. Symmetric: If x.equals(y) is true, then y.equals(x) must be true.

    c. Transitive: If x.equals(y) is true, and y.equals(z) is true, then z.equals(x) is true.

    d. Consistent: Multiple calls to x.equals(y) will return the same result.

    e. Null: If x is not null, then x.equals(null) is false.

    f. If x.equals(y) is true, then x.hashCode() == y.hashCode() is true.
  • If you override equals(), override hashCode().
  • HashMap, HashSet, Hashtable, LinkedHashMap, & LinkedHashSet use hashing.
  • An appropriate hashCode() override sticks to the hashCode() contract.
  • An efficient hashCode() override distributes keys evenly across its buckets.
  • An overridden equals() must be at least as precise as its hashCode() mate.
  • To reiterate: if two objects are equal, their hashcodes must be equal.
  • It's legal for a hashCode() method to return the same value for all instances (although in practice it's very inefficient).

In addition if you implement equals and hashcode the transient fields (if any) must be treated properly.

The Commons have nice implementation for EqualsBuilder and HashcodeBuilder. They are available in Coomons Lang
http://commons.apache.org/lang/

I use them whenevr I need to implement the equals and the hashcode.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文