Java Hashset.contains()产生神秘结果 [英] Java Hashset.contains() produces mysterious result
问题描述
我通常不使用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 时, code>,它将解析为基本的
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屋!