来自c ++世界,我发现阅读HashSet文档有点困难:
在c ++中,您将拥有:
反过来指向:
这明显要求std::set
处理的元素类型。我的问题是:Java中Set
维护的元素类型(E)有哪些要求?
这是一个我无法理解的简短例子:
import gdcm.Tag;
import java.util.Set;
import java.util.HashSet;
public class TestTag
{
public static void main(String[] args) throws Exception
{
Tag t1 = new Tag(0x8,0x8);
Tag t2 = new Tag(0x8,0x8);
if( t1 == t2 )
throw new Exception("Instances are identical" );
if( !t1.equals(t2) )
throw new Exception("Instances are different" );
if( t1.hashCode() != t2.hashCode() )
throw new Exception("hashCodes are different" );
Set<Tag> s = new HashSet<Tag>();
s.add(t1);
s.add(t2);
if( s.size() != 1 )
throw new Exception("Invalid size: " + s.size() );
}
}
上述简单代码失败了:
Exception in thread "main" java.lang.Exception: Invalid size: 2 at TestTag.main(TestTag.java:42)
从我对文档的阅读中,只需要为Set:
实现equals运算符文档中缺少什么?
答案 0 :(得分:2)
我只是尝试重现您的问题,也许您只是没有正确覆盖equals和/或hashSet。
看看我错误的Tag实现:
public class Tag {
private int x, y;
public Tag(int x, int y) {
this.x = x;
this.y = y;
}
public boolean equals(Tag tag) {
if (x != tag.x) return false;
return y == tag.y;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
看起来很好没有吗?但问题是,我实际上没有覆盖正确的equals方法,我用自己的实现重载了它。
要正常工作,equals必须如下所示:
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tag tag = (Tag) o;
if (x != tag.x) return false;
return y == tag.y;
}
答案 1 :(得分:1)
文档中缺少什么?
您正在查看文档的错误部分。
C ++ set
是一个“排序的唯一对象集”,并且“通常实现为红黑树。”
在Java中,Set
是一个更抽象的概念(它是一个接口,而不是一个类),具有多个实现,最值得注意的是HashSet
和TreeSet
(忽略并发)实现)
正如您可能只从名称中猜到的那样,Java TreeSet
相当于C ++ set
。
对于要求,HashSet
使用hashCode()
和equals()
方法。它们是在Object
类上定义的,需要在需要HashSet
的类或HashMap
中的键中重写。
对于TreeSet
和TreeMap
的密钥,您有两种选择:在创建TreeSet
(类似于C ++)时提供Comparator
,或让对象实现Comparable
界面。
答案 2 :(得分:0)
我想这只是运气不好和对HashSet要求的误解的结合。感谢@christophe的帮助,当我尝试添加swig生成的Tag.java类时,我意识到了这个问题:
@Override
public boolean equals(Object o) {
}
我收到以下错误消息:
gdcm/Tag.java:78: error: method does not override or implement a method from a supertype
@Override
^
1 error
1 warning
这意味着我的错误很简单:
boolean equals(Object o)
!= boolean equals(Tag t)
提示只是使用@Override
关键字。
对于那些要求上游代码的人来说,Java代码是由swig生成的。原始的c ++代码在这里:
答案 3 :(得分:-3)
大小为2(不等于1),因此抛出异常(最后一行代码)。 编辑:也许我以前没有理解你。通常,类型E是您选择的任何类型。例如:put Object或&#39;?&#39;会让你能够放任何类型。在您的情况下,您选择标记作为类型E,因此它应该是集合的内容。