今天遇到一件怪事,用一个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. Flutter——AspectRatio组件

    AspectRatio 的作用是根据设置调整子元素 child 的宽高比. AspectRatio 首先会在布局限制条件允许的范围内尽可能的扩展,widget 的高度是由宽度和比率决定的,类似于 Bo ...

  2. 微信小程序开发(十三)安卓手机调用wx.getConnectedWifi API失败

    安卓手机调用wx.getConnectedWifi API失败,返回的错误码是12000.需要先startWifi 接口: wx.startWifi({ success(res) { console. ...

  3. 文件格式 rdp

    auto connect:i:1full address:s:公网访问IP地址username:s:Administrator

  4. JDK源码那些事儿之我眼中的HashMap

    源码部分从HashMap说起是因为笔者看了很多遍这个类的源码部分,同时感觉网上很多都是粗略的介绍,有些可能还不正确,最后只能自己看源码来验证理解,写下这篇文章一方面是为了促使自己能深入,另一方面也是给 ...

  5. VSCode 的PHP常用插件及安装

    一.在程序中打断点调试:PHP Debug 二.高级自动完成和重构支持(代码智能提示):PHP IntelliSense 配置: "php.suggest.basic": fals ...

  6. OPT

    http://cdn.imgtec.com/sdk-documentation/PowerVR.Performance+Recommendations.pdf 宝贝 https://developer ...

  7. 【JUC系列第一篇】-Volatile关键字及内存可见性

    作者:毕来生 微信:878799579 什么是JUC? JUC全称 java.util.concurrent 是在并发编程中很常用的实用工具类 2.Volatile关键字 1.如果一个变量被volat ...

  8. Python14__网络SOCKET

  9. HR#4 题解

    既然考这么差就来写题啦OTZ T1 猜结论?猜nm! 一直到考试结束都没猜出来=.=我就好奇别人如何猜出来的 我们来说DP(from ZBK) 设\(dp[i][j]\)表示胜or负 那我们来看一下代 ...

  10. PHP mysqli_commit() 函数

    关闭自动提交,做一些查询,然后提交查询: <?php // 假定数据库用户名:root,密码:123456,数据库:RUNOOB $con=mysqli_connect("localh ...