为什么存储了1L的HashSet<Long>调用contains(1)返回false?
Java代码运行结果异常原因解析
public static void main(String[] args) { List<Long> list = Arrays.asList(1l,2l,3l); Set<Long> set = new HashSet<>(list); System.out.println(set); // [1, 2, 3] System.out.println(set.contains(1)); // false }
核心原因拆解
- 自动装箱逻辑限制
Java的自动装箱只会将基础类型转换为对应包装类:int类型的1只会被装箱为Integer对象,不会先做基础类型提升转为long再装箱为Long对象。set.contains(1)传入的int值1最终会被转为Integer类型对象进入方法逻辑。 - 集合
contains方法的签名设计
Java集合框架的contains方法签名为boolean contains(Object o),参数接收任意Object类型,并不会受集合泛型限制。所以哪怕你声明的是Set<Long>,传入Integer类型的参数也不会触发编译期的类型转换或者报错,编译器不会主动完成Integer到Long的类型转换。 - 元素匹配规则不匹配
HashSet判断元素是否存在时,先比对两个对象的hashCode,再调用equals方法校验相等。即使Integer(1)和Long(1)的hashCode计算结果相同,二者的equals判断也会返回false:所有包装类的equals方法都会先校验入参的类型是否和自身一致,类型不同直接返回false,不会比较实际数值是否相等。 - 打印结果的误导
控制台打印Set内容时会调用元素的toString方法,Long类型的toString仅输出数值本身,不会附带L后缀,所以看起来和int类型的1没有区别,实际二者是完全不同类型的对象。
解决方案
调用contains方法时传入long类型的1即可,写法为set.contains(1L),此时参数会自动装箱为Long类型,和集合内的元素类型匹配,即可返回正确的true结果。
内容的提问来源于stack exchange,提问作者maplemaple
相关产品推荐
相关产品推荐

