List的remove方法
List的Remove方法在删除元素的时候总会保持下标连续。例如,删掉第一个元素的时候,后面的元素会依次往前覆盖。
两个简单的例子,帮助了解remove()方法删除的基本原则:
ArrayList<String> list= new ArrayList<String>();
list.add("tom");
list.add("jim");
list.remove("tom");
System.out.println(list.size());//输出结果为1
ArrayList<Integer> list= new ArrayList<Integer>();
list.add(11);
list.add(12);
list.remove(0);//删除0号位置的元素
System.out.println(list.size());//输出结果为1
for (Integer integer : list) {
System.out.println(integer);
}//输出结果为12
不难看出remove()方法删除的规则:删除String类型比较内容是否相同,删除基本数据类型的包装类时比较数值是否相同;
为了方便继续讨论,我们先创建如下代码
ArrayList<Person> list= new ArrayList<Person>();
Person per1=new Person();
Person per2=new Person();
list.add(per1);
list.add(per2);
list.remove(per2);
再创建一个Person类
public class Person {
public String id;
public Person() {
this.id = id;
}
// 重写Object类中的equals()方法
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}
此时ArrayList中的remove方法调用的是传入参数(例中为per2)的equals()方法
其底层代码如下:
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
此时再来分析一次,如果传入的参数为空,执行if{}中的代码
着重分析传入的参数不为空的情况,执行else后的代码:先for循环遍历集合,再进入if的判断部分,继而调用传入对象的equals()方法,如果该对象没有重写equals()方法,则调用从Object()继承的equals()方法[Object类是所有类的父类]
此时执行代码会发现,删除并没有成功。
???(黑人问号脸)不要着急
思考不难发现,调用remove方法的时候其实是调用Person中的equals方法,因为Person类并没有重写Object中的equals方法,所以调用的还是Object中的equals方法,本质上还是比较两个对象的内存地址。
我们不如趁火打劫哦不趁热打铁,在Person类中重写Object中的equals方法emmm就是这个样子了
@Override
public boolean equals(Object obj) {
return this.id.equals(person.id);
}
再执行是不是就正确了-----.-----
你以为这样就结束了??别急我们看个奇怪的东西
如果我们这样:(Dog.class请自行创建)
ArrayList<Object> list = new ArrayList<>();
list.add(new Dog())
list.add(new Person("1"));
System.out.println(list.size());//2
list.remove(new Person("1"));
System.out.println(list.size());
此时代码执行会出错,仔细一想,WTF竟然是在上转型转换为下转型对象时出了问题,读读代码emmm把Dog转换成…
这不是要笑skr人,还好我们还有一招
@Override
public boolean equals(Object obj) {
if (obj instanceof Person) {
Person person = (Person) obj;上转型对象不能调用子类新增的属性和方法因此需要上转型转换为下转型
return this.id.equals(person.id);
}else {
return false;
}
}
管你什么妖魔鬼怪,这下还不把你收拾的服服帖帖。
最后再bb两句
如果将ArrayList的泛型设置为Integer时,想要使用remove(Object obj)方法,则需要注意传入的参数必须为Integer,而不是整数值。
如果还有需要补充的我会随时修改。。。