java 记录一下使用集合中的contains方法遇到的小问题

		Long a = 10000L;
       Long b = 10000L;
       List<Long> test = new ArrayList<>();
       test.add(a);
       System.out.println(test.contains(b));

大家都知道,Long以及Integer 都是有个常量缓存池,为-128 到127这个范围。这个范围内的对象都是相等的。

 private static class LongCache {
        private LongCache(){}

        static final Long cache[] = new Long[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Long(i - 128);
        }
    }

就是说

Long a = 100L;
Long b = 100L
System.out.println(a == b)

返回值为true的。因为这段区间的值属于常用值,所以即使新建在多的对象也是同一个值。
但回到上题, 笔者新建了两个Long对象,给对象赋值都超过了Long自带的常量缓存区间,所以这两个对象完全是不相等的。读者只加入了第一个对象,但运行结果是true。list集合判断包含b这个对象,可明明读者就没有往集合里添加该对象。

接下来,读者看了下源码。
从list集合接口里contains方法找到ArrayList的实现, 再定位到具体调用的方法。

   public int indexOf(Object o) {
   // 先判断入参是否为null
        if (o == null) {
        // 为null就循环判断elementData数组是否包含null
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
        // 不为null就调用对象的equals方法去比较
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

调用对象的equals方法,查看Long的equals方法。


 public boolean equals(Object obj) {
 // 判断是否为Long对象
        if (obj instanceof Long) {
        // 比较的是拆箱的long类型值。
            return value == ((Long)obj).longValue();
        }
        return false;
    }

从上就可了解了为何两个不同的Long对象,只要值相同,list contains()方法就返回true。
同理,Integer,String这些不可变类的结果也是一样。这也解释了为何新建两个对象,其属性值一样,为何contains()失败。因为对象的equals()方法没有重写的话,默认就是比较地址值。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值