为什么设置允许重复的字节整数和长整型值

问题描述:

由于我的知识集基本上有两个方法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个实例并不相同。

见,例如,Integerequals

public boolean equals(Object obj) { 
    if (obj instanceof Integer) { 
     return value == ((Integer)obj).intValue(); 
    } 
    return false; 
} 

两个实例必须是相同的类型,以便为彼此相等(必要条件)。

+0

长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

+0

谢谢你了! – pranta

设置不允许重复的值。这里的问题是什么是重复的,什么不重要。

重复值是那些相同类型,具有相同的hashCode(),并且在比较时也返回true。不同类型的对象(在你的例子中是Byte和Long)在这些术语中是不相等的。

如果您想然而把不同的数字类型的值转换成集,并享受跨类型的行为,你可以使用TreeSet与自定义Comparator,只有不考虑类型考虑比较。

+0

让我挑剔(对不起):“重复的值是那些同类型的[...]” =>虽然它应该是真实的,它是完全由_equals_实施,而不是一个集合的特性。既然这样,这句话是有点误导,不是吗? – Seelenvirtuose

+0

你是对的,它是等于执行。然而,OP使用已经实现了equals的原始包装。 – AlexR

这里是什么javadocInteger.equals(Object)说:

比较此对象与指定对象。结果为真当且仅当参数不是null并且是一个Integer对象包含与此对象相同的int值。

换句话说,一个Integer对象不能等于一个也不是Integer对象的对象。这同样适用于所有的基本包装类。

因此,根据HashSet的语义,您示例中的那4个对象不相同,因此不会重复。


不幸的是,如果你使用HashSet或任何其他标准的Java基于哈希表类的,与标准的包装类一起,对于这个没有解决方法。

但是:

  • 如果你使用TreeSet或类似的,你可以使用自定义Comparator对象解决此问题。

  • Guava中有一个替代的哈希表实现,允许您提供外部equals和hashCode实现。

  • 你可以用不同的语义创建你自己的包装类,用于equals和hashcode到标准类。不幸的是,这些不会与其他事物进行互操作。例如Java自动装箱/自动拆箱。