Java 为什么Set允许重复字节整数值和长数值
由于我的知识集基本上有两个方法equals()和hashcode(),根据这两个方法确定包含的值相等并避免重复条目,但在我感到困惑的程序下面,即使包装器类也重写了这两个方法,那么为什么它接受重复的值呢 代码:Java 为什么Set允许重复字节整数值和长数值,java,set,Java,Set,由于我的知识集基本上有两个方法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.prin
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
实例,即使两者具有相同的数值。您在集合中放置的3个实例彼此不相等
例如,请参见整数
的等于
:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
两个实例必须具有相同的类型才能彼此相等(这是一个必要条件)。集合不允许重复值。这里的问题是什么是重复的,什么不是
重复值是指具有相同类型、具有相同hashCode()且在比较时返回true
的值。不同类型的对象(在您的例子中是Byte和Long)在这些术语中并不相等
但是,如果您想将不同数值类型的值放入集合并享受交叉类型行为,您可以使用自定义的比较器使用TreeSet
,该比较器只比较值,而不考虑类型 下面是forInteger.equals(Object)
的说明:
将此对象与指定对象进行比较。当且仅当参数不是null
且是包含与此对象相同int值的整型对象时,结果才为真
换句话说,整数
对象不能等于不同时也是整数
对象的对象。这同样适用于所有基本包装器类
因此,根据HashSet
的语义,示例中的这4个对象不相等,因此不重复
不幸的是,如果您使用的是HashSet
或任何其他基于Java哈希表的标准类,以及标准包装类,则没有解决方法
然而:
- 如果要使用
TreeSet
或类似工具,可以使用自定义Comparator
对象解决此问题
- Guava中有另一种哈希表实现,允许您提供外部equals和hashCode实现
- 您可以为标准类创建具有不同语义的equals和hashcode包装器类。不幸的是,它们不能与其他东西互操作;e、 g.Java自动装箱/自动取消装箱
长l=新长(65);系统输出打印LN(l);整数it=新的整数(65);System.out.println(it);System.out.println(l等于(it));让我来挑剔一下(对不起):“重复值是那些类型相同的值[…]”=>虽然应该是真的,但它完全取决于equals实现,而不是集合的特征。就目前而言,这句话有点误导人,不是吗?你是对的,这取决于平等的实现。然而,OP使用的是已经实现了equals的基本包装器。