Java Hashset.contains()产生神秘结果 [英] Java Hashset.contains() produces mysterious result

查看:249
本文介绍了Java Hashset.contains()产生神秘结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通常不使用Java编写代码,但是最近我开始别无选择。我可能对如何正确使用HashSet有一些重大的误解。因此,我所做的某些事情可能完全是错误的。不过,如果您能提供任何帮助,我将不胜感激。因此,实际的问题是:

I don't usually code in Java, but recently I started not having a choice. I might have some major misunderstanding of how to properly use HashSet. So it might be possible something I did is just plain wrong. However I'm grateful for any help, you might offer. So the actual problem:

在我编写的一个小程序中,我生成了非常相似的对象,这些对象在创建时将具有非常特定的id(a string 或在我的上一个迭代中为 long )。因为每个对象都会产生新的对象,所以我想过滤掉所有已经创建的对象。因此,我开始将每个新对象的ID都放入Hash(Set)中,并使用 HashSet.contains()进行测试(如果之前已创建对象)。这是完整的代码:

In a small program I was writing, I was generating very similar objects, which, when created, would have a very specific id (a string or in my last iteration a long). Because each object would spawn new objects, I wanted to filter out all those I already created. So I started throwing the id of every new object into my Hash(Set) and testing with HashSet.contains(), if an object was created before. Here is the complete code:

// hashtest.java
import java.util.HashSet;

class L {
    public long l;
    public L(long l) {
        this.l = l;
    }
    public int hashCode() {
        return (int)this.l;
    }
    public boolean equals(L other) {
        return (int)this.l == (int)other.l;
    }
}

class hashtest {
    public static void main(String args[]) {
        HashSet<L> hash = new HashSet<L>();
        L a = new L(2);
        L b = new L(2);
        hash.add(a);
        System.out.println(hash.contains(a));
        System.out.println(hash.contains(b));
        System.out.println(a.equals(b));
        System.out.println(a.hashCode() == b.hashCode());
    }
}

产生以下输出:

true
false
true
true    

因此,显然,包含不使用由提供的等于函数 L ,或者我对该概念有一些重大误解...

so apparently, contains does not use the equals function provided by L, or I have some major misunderstanding of the concept ...

我用openjdk进行了测试(当前版本包括在ubuntu中)和Win7上Oracle上的Java当前官方版本

I tested it with openjdk (current version included in ubuntu) and the official current java from Oracle on Win7

,以获取 HashSet.contains()


公共布尔包含(对象o)

如果此集合包含
指定的元素,则返回 true 。更正式地说,当且仅当此集合
包含元素 e 时,
才会返回 true
(o == null?e == null:o.equals(e))

Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).

http://download.oracle.com/javase/6/docs/api/java/util/HashSet.html#contains(java.lang.Object)

有什么想法或建议吗?

推荐答案

您的相等方法需要采用 Object

因为您声明它为采用 L ,它将成为附加的重载而不是覆盖方法。

因此,当 hashSet 类调用 equals ,它将解析为基本的 Object.equals 方法。当您调用等于时,您会调用过载,因为 a b 都被声明为 L 而不是 Object

Your equals method needs to take an Object.
Because you declared it as taking an L, it becomes an additional overload instead of overriding the method.
Therefore, when the hashSet class calls equals, it resolves to the base Object.equals method. When you call equals, you call your overload because a and b are both declared as L instead of Object.

为防止将来出现此问题,每当您重写方法时,都应添加 @Override

这样,编译器会警告您它是否实际上不是替代。

To prevent this issue in the future, you should add @Override whenever you override a method.
This way, the compiler will warn you if it isn't actually an override.

这篇关于Java Hashset.contains()产生神秘结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆