为什么设置允许重复的字节整数和长整型值
由于我的知识集基本上有两个方法equals()和hashcode(),根据它确定的值包含的值相等并避免重复输入,但是在下面的程序中我得到困惑,即使包装类也有两种方法重写,那么为什么它接受重复值?为什么设置允许重复的字节整数和长整型值
代码:
Collection col=new LinkedHashSet();
col.add(new Long(65));
col.add(new Byte((byte) 65));
col.add(new Integer(65));
col.add("A");
System.out.println(col);
答:65,65,65,A] 但我预期[65,A]
一个Long
实例可以永远不等于一个Integer
实例即使两者具有相同的数值,它也永远不会等于Byte
实例。你放入Set
的3个实例并不相同。
见,例如,Integer
的equals
:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
两个实例必须是相同的类型,以便为彼此相等(必要条件)。
设置不允许重复的值。这里的问题是什么是重复的,什么不重要。
重复值是那些相同类型,具有相同的hashCode(),并且在比较时也返回true
。不同类型的对象(在你的例子中是Byte和Long)在这些术语中是不相等的。
如果您想然而把不同的数字类型的值转换成集,并享受跨类型的行为,你可以使用TreeSet
与自定义Comparator
,只有不考虑类型考虑值比较。
让我挑剔(对不起):“重复的值是那些同类型的[...]” =>虽然它应该是真实的,它是完全由_equals_实施,而不是一个集合的特性。既然这样,这句话是有点误导,不是吗? – Seelenvirtuose
你是对的,它是等于执行。然而,OP使用已经实现了equals的原始包装。 – AlexR
这里是什么javadoc为Integer.equals(Object)
说:
比较此对象与指定对象。结果为真当且仅当参数不是
null
并且是一个Integer
对象包含与此对象相同的int值。
换句话说,一个Integer
对象不能等于一个也不是Integer
对象的对象。这同样适用于所有的基本包装类。
因此,根据HashSet
的语义,您示例中的那4个对象不相同,因此不会重复。
不幸的是,如果你使用HashSet
或任何其他标准的Java基于哈希表类的,与标准的包装类一起,对于这个没有解决方法。
但是:
如果你使用
TreeSet
或类似的,你可以使用自定义Comparator
对象解决此问题。Guava中有一个替代的哈希表实现,允许您提供外部equals和hashCode实现。
你可以用不同的语义创建你自己的包装类,用于equals和hashcode到标准类。不幸的是,这些不会与其他事物进行互操作。例如Java自动装箱/自动拆箱。
长L =新龙(65); \t \t System.out.println(l); \t \t Integer it = new Integer(65); \t \t System.out.println(it); \t \t System.out.println(l.equals(it)); – pranta
谢谢你了! – pranta