今天遇到一件怪事,用一个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)。

List的remove方法里的坑的更多相关文章

  1. 关于List的remove方法我遇到的坑

    结果是下标越界异常,原因是remove方法的参数不是value,而是index 唉~~~  年少轻狂啊

  2. 为什么Java里的Arrays.asList不能用add和remove方法?

    在平时的开发过程中,我们知道能够将一个Array的对象转化为List.这种操作,我们仅仅要採用Arrays.asList这种方法即可了.笔者前段时间一直用这种方法,有一天,我发现通过Arrays.as ...

  3. EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解

    前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...

  4. Datatable删除行的Delete和Remove方法

    在C#中,如果要删除DataTable中的某一行,大约有以下几种办法: 1,使用DataTable.Rows.Remove(DataRow),或者DataTable.Rows.RemoveAt(ind ...

  5. [置顶] 有关ListIterator接口的add与remove方法探究

    ListIterator接口继承自Iterator接口,新增了add()等方法. 关于ListIterator的add()方法的作用(接口是没有方法实现的,但其实现类对于add()方法的实现机制大致相 ...

  6. ThreadLocal源码分析:(三)remove()方法

    在ThreadLocal的get(),set()的时候都会清除线程ThreadLocalMap里所有key为null的value. 而ThreadLocal的remove()方法会先将Entry中对k ...

  7. Java基础(37)ArrayList的remove方法

    1.问题描述 给定两个字符串 s 和 t,它们只包含小写字母. 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母. 请找出在 t 中被添加的字母. 输入: s = "abcd& ...

  8. List的remove()方法的三种正确打开方式

    转: java编程:List的remove()方法的三种正确打开方式! 2018年08月12日 16:26:13 Aries9986 阅读数 2728更多 分类专栏: leetcode刷题   版权声 ...

  9. Spring里的坑

    Spring里的坑 1. 配置文件配置controller,在Controller中使用注解配置的bean,会出现获取不到bean的情况 步骤一:使用在配置文件 springmvc.xml 中配置的方 ...

随机推荐

  1. github安全整理

    漏洞及渗透练习平台: WebGoat漏洞练习平台: https://github.com/WebGoat/WebGoat webgoat-legacy漏洞练习平台: https://github.co ...

  2. Ubuntu安装cmake 3.9

    wget https://cmake.org/files/v3.9/cmake-3.9.2.tar.gz # 下载 cd cmake-3.9.2 ./configure sudo make & ...

  3. selenium 显示等待wait.until 常用封装 及下拉框的选择操作等

    from selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWait a ...

  4. Week08_day01 (Hive实现按照指定格式输出每七天的消费平均数)

    Hive实现按照指定格式输出每七天的消费平均数 数据准备 2018/6/1,10 2018/6/2,11 2018/6/3,11 2018/6/4,12 2018/6/5,14 2018/6/6,15 ...

  5. PHP 获取上传文件的实际类型

    方案一: mime_content_type ( string $filename ) : string (PHP 4 >= 4.3.0, PHP 5, PHP 7) mime_content_ ...

  6. Java集合--Map总结

    转载请注明出处:http://www.cnblogs.com/skywang12345/admin/EditPosts.aspx?postid=3311126 第1部分 Map概括 (01) Map ...

  7. flask 杂记

    参考资料:http://python.jobbole.com/84003/  https://flask-cn.readthedocs.io/en/latest/tutorial/ 加载配置: app ...

  8. centos ntfs-3g not find

    1,CentOS默认源里没有ntfs3g,想要添加ntfs支持,需要自己下载编译安装或者加源yum安装.我这里使用的是添加aliyun的epel源来yum安装的方式. 2,添加epel yum源wge ...

  9. request.querystring和request.form的区别

    1,request.querystring和request.form的区别 request.querystring是用来接收地址里面问号“?”后面的参数的内容,  用get方法读取的 不安全 requ ...

  10. web上传下载文件

    WebService代码: ///     /// 上传文件     ///     /// 文件的byte[]     /// 上传文件的路径     /// 上传文件名字     ///     ...