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)。
List的remove方法里的坑的更多相关文章
- 关于List的remove方法我遇到的坑
结果是下标越界异常,原因是remove方法的参数不是value,而是index 唉~~~ 年少轻狂啊
- 为什么Java里的Arrays.asList不能用add和remove方法?
在平时的开发过程中,我们知道能够将一个Array的对象转化为List.这种操作,我们仅仅要採用Arrays.asList这种方法即可了.笔者前段时间一直用这种方法,有一天,我发现通过Arrays.as ...
- EntityFramework Core 1.1 Add、Attach、Update、Remove方法如何高效使用详解
前言 我比较喜欢安静,大概和我喜欢研究和琢磨技术原因相关吧,刚好到了元旦节,这几天可以好好学习下EF Core,同时在项目当中用到EF Core,借此机会给予比较深入的理解,这里我们只讲解和EF 6. ...
- Datatable删除行的Delete和Remove方法
在C#中,如果要删除DataTable中的某一行,大约有以下几种办法: 1,使用DataTable.Rows.Remove(DataRow),或者DataTable.Rows.RemoveAt(ind ...
- [置顶] 有关ListIterator接口的add与remove方法探究
ListIterator接口继承自Iterator接口,新增了add()等方法. 关于ListIterator的add()方法的作用(接口是没有方法实现的,但其实现类对于add()方法的实现机制大致相 ...
- ThreadLocal源码分析:(三)remove()方法
在ThreadLocal的get(),set()的时候都会清除线程ThreadLocalMap里所有key为null的value. 而ThreadLocal的remove()方法会先将Entry中对k ...
- Java基础(37)ArrayList的remove方法
1.问题描述 给定两个字符串 s 和 t,它们只包含小写字母. 字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母. 请找出在 t 中被添加的字母. 输入: s = "abcd& ...
- List的remove()方法的三种正确打开方式
转: java编程:List的remove()方法的三种正确打开方式! 2018年08月12日 16:26:13 Aries9986 阅读数 2728更多 分类专栏: leetcode刷题 版权声 ...
- Spring里的坑
Spring里的坑 1. 配置文件配置controller,在Controller中使用注解配置的bean,会出现获取不到bean的情况 步骤一:使用在配置文件 springmvc.xml 中配置的方 ...
随机推荐
- python之分支和循环
Day 1-night 三元操作符 语法:a=x if 条件 else y 即:当条件为True时,a的值赋值为x,否则赋值为y eg:small=x if x<y else y <=& ...
- python基础应用---格式化输出
python的格式化输出,原来不是很理解,现在有点了解了,为此特意写一个博客来记录一下,以便自己会忘记了,随时查看, 程序主体 #格式化输出之一 name = input("pls inpu ...
- 一个异常研究InvalidApartmentStateChange
微软资料:invalidApartmentStateChange MDA 地址:https://docs.microsoft.com/zh-cn/dotnet/framework/debug-trac ...
- 修改HTTPS加密协议TLS1.0为TLS1.2
一:首先为什么要改为TLS1.2 因为各大浏览器相继发布声明将停止支持 TLS 1.0 和 TLS 1.1 https://www.cnblogs.com/jpush88/p/9846047.html ...
- 详解Python 切片语法
Python的切片是特别常用的功能,主要用于对列表的元素取值.这篇文章主要介绍了详解Python 切片语法,需要的朋友可以参考下 Python的切片是特别常用的功能,主要用于对列表的元素取值.使用切片 ...
- 第一次的django 和html的插肩而过
新建一个Python Django工程: Win+R进入cmd命令界面,并cd到指定工程目录下,比如我的工程目录是E:\wamp\Apache24\www\ 输入E: 跳转E盘 输入cd wamp\A ...
- 顺序表Vector
程序中会使用数据结构:例如:顺序表.链表.二叉树: 数据结构在底层中本质上只有两种:数据之间挨着和不挨着: 1.关于Vector
- ES6-12.Symbol
Symbol是ES6新增的原始类型数据,引入的初衷是为了对象可以有永不重复的属性名. 所以属性名可以是字符串外,还可以是Symbol值: const a = Symbol("a") ...
- 029_检测 MySQL 数据库连接数量
#!/bin/bash#本脚本每 2 秒检测一次 MySQL 并发连接数,可以将本脚本设置为开机启动脚本,或在特定时间段执行#以满足对 MySQL 数据库的监控需求,查看 MySQL 连接是否正常#本 ...
- ueditor+word粘贴上传!
图片的复制无非有两种方法,一种是图片直接上传到服务器,另外一种转换成二进制流的base64码 目前限chrome浏览器使用,但是项目要求需要支持所有的浏览器,包括Windows和macOS系统.没有办 ...