zoukankan      html  css  js  c++  java
  • List的remove方法里的坑

      今天遇到一件怪事,用一个ArrayList添加了一个对象,再调用ArrayList的remove方法删除该对象,当然这时对象是数据库里查出来的,但内容绝对是一样,却发现remove失败了。演示一下,这里用了自定义的Merchant对象,测试时只需随便自定义一个对象即可:

      

      public static void main(String[] args) {
            List<Merchant> merchants = new ArrayList<>();
            Merchant merchant = new Merchant();
            merchant.setMerchantId("aa");
            merchant.setMarketPlaceId("bb");
            merchant.setSecretKey("aa");
            merchant.setAccessKeyId("bb");
            merchants.add(merchant);
            Merchant other = new Merchant();
            other.setMerchantId("aa");
            other.setMarketPlaceId("bb");
            other.setSecretKey("aa");
            other.setAccessKeyId("bb");
    
            boolean isRemoved = merchants.remove(other);
    
            System.out.println(isRemoved);
        }

      结果打印出来是false。然后去看了一下ArrayList的remove方法:

        public boolean remove(Object var1) {
            int var2;
            if (var1 == null) {
                for(var2 = 0; var2 < this.size; ++var2) {
                    if (this.elementData[var2] == null) {
                        this.fastRemove(var2);
                        return true;
                    }
                }
            } else {
                for(var2 = 0; var2 < this.size; ++var2) {
                    if (var1.equals(this.elementData[var2])) {
                        this.fastRemove(var2);
                        return true;
                    }
                }
            }
    
            return false;
        }
    
        private void fastRemove(int var1) {
            ++this.modCount;
            int var2 = this.size - var1 - 1;
            if (var2 > 0) {
                System.arraycopy(this.elementData, var1 + 1, this.elementData, var1, var2);
            }
    
            this.elementData[--this.size] = null;
        }

       关键在标黄那一行,remove的前提是两个对象的equals方法必须相等,而我定义的Merchant对象并无复写Object类的equals方法,那么执行到这一行时equals就是Object的equals方法:

        public boolean equals(Object obj) {
            return (this == obj);
        }

      是否一下子有种恍然大悟的被坑的感觉?反正我是这样子觉得的,Object类比较的是引用,而main里测试的是两个不同的引用,equals必然是false,remove自然也是false了,不信可以把equals也一并打印一下:

        public static void main(String[] args) {
            List<Merchant> merchants = new ArrayList<>();
            Merchant merchant = new Merchant();
            merchant.setMerchantId("aa");
            merchant.setMarketPlaceId("bb");
            merchant.setSecretKey("aa");
            merchant.setAccessKeyId("bb");
            merchants.add(merchant);
            Merchant other = new Merchant();
            other.setMerchantId("aa");
            other.setMarketPlaceId("bb");
            other.setSecretKey("aa");
            other.setAccessKeyId("bb");
    
            boolean isRemoved = merchants.remove(other);
    
            System.out.println(other.equals(merchant));
            System.out.println(isRemoved);
        }

      你会发现两个false出现了。那么咋办呢?很简单,既然是equals引起的,那就让它来解决问题,我们再Merchant里重写Object的equals即可。当然既然重写了equals,我们也得把hashCode方法也一起重写一下,现在的IDE都很智能,自动生成即可。等你的自定义类生成好了这俩方法后,重新执行上面这个main,你会发现出现俩true了。

      当然,如果你希望在自定义的对象里修改了非关键属性(比如上面的Merchant里的accessKeyId、secretKey等这些属性,在数据库update他们的值之后就都改变了)都不影响该对象的唯一性,那么我们可以把equals和hashCode方法里自动生成的其他属性去掉,只保留能识别该对象的关键属性(比如merchantId)。

  • 相关阅读:
    继承中的虚函数、纯虚函数、普通函数
    struct与class的区别
    boost::filesystem总结
    ASM: Active Shape Models--Their Training and Application
    基础知识:仿射变换、相似变换、等距变换等常见变换
    PDM:Training Models of Shape from Sets of Examples
    常见优化器
    深度学习基础(五)ResNet_Deep Residual Learning for Image Recognition
    深度学习基础(四) Dropout_Improving neural networks by preventing co-adaptation of feature detectors
    ios 各种变量和作用范围
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/10887511.html
Copyright © 2011-2022 走看看