List中的remove()方法执行过程
先创建一个List集合对象并添加元素
List<Person> list = new ArrayList<Person>();
Person p1 = new Person();
Person p2 = new Person();
Person p3 = new Person();
list.add(p1);
list.add(p2);
list.add(p3);
其中创建Person类
public class Person {
// 设置计数变量,每次执行一次count就增加一
private static int count = 0;
// 重写Object类中的equals()方法
@Override
public boolean equals(Object obj) {
System.out.println(this + "======" + count++);
return super.equals(obj);
}
}
- ArrayList中remove()方法主要调用了传入对象的equals()方法
//ArrayList源码如下
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;
}
主要过程
上面我们已经创建出来了ArrayList集合对象并向里面添加了三个不同的元素
// 调用remove()方法
list.remove(new Person);
如果传入的对象不为空,那就直接执行else里面的代码
- 首先遍历集合,进去if语句
- 调用传入对象的equals()方法,如果该对象没有重写equals()方法则调用从Object()继承的equals()方法
在Person类中定义一个用来计数的静态变量count,将其再equals()方法中打印,每执行一次则count就会加一
这里给remove()方法中传入了一个Person类的对象,执行结果如下
System.out.println(list.remove(new Person()));
System.out.println(list.size());
输出的结果
com.xingtang.test1.Person@7852e922======count = 0
com.xingtang.test1.Person@7852e922======count = 1
com.xingtang.test1.Person@7852e922======count = 2
false
3
这里可以看出Person类中的equals()方法执行了三次,并且删除失败,ArrayList中的元素并没有减少这是因为
1.remove()方法根据List的长度为次数执行循环,这里List集合中共有三个元素那么就循环执行了三次,每次都在if语句中调用了Person的equals()方法
2.因为调用了Object类中的equals方法,则删除的时候是比较两个对象的地址值是否相同,如果相等则删去对象。又因为这里的创建了一个新的Person对象(new Person())这里没有和新创建的对象地址值相同的元素,所以会删除失败。所以调用list.size()结果仍是3。
————————————————————————————————————————————————————————
重写equals()方法删除属性相同的(符合特定条件的)对象
给Person类中定义一个name属性和id属性,如果两个对象的name和id相同,则认为这两个对象相等,将其删除。
- Person类
public class Person {
// 声明属性
private String name;
private String id;
// 构造方法
public Person() {
}
public Person(String name, String id) {
this.name = name;
this.id = id;
}
// getter方法和setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
// 重写Object的equals方法
@Override
public boolean equals(Object obj) {
Person person = (Person)obj;
//如果本对象和将要比较的对象的name和id相同则返回true
return (this.id.equals(person.getId())
&& this.name.equals(person.getName()));
}
编写测试类
// 创建一共ArrayList集合添加三个属性不同的元素
List<Person> list = new ArrayList<Person>();
Person p1 = new Person("ZhangSan","1");
Person p2 = new Person("LiSi","2");
Person p3 = new Person("WangWu","3");
list.add(p1);
list.add(p2);
list.add(p3);
// 删除前元素的个数
System.out.println(list.size());
System.out.println(list.remove(new Person("LiSi","2")));
// 删除后元素的个数
System.out.println(list.size());
// 遍历List中的元素
for (Person p : list) {
System.out.println("name=" + p.getName() + ", id=" + p.getId());
}
输出结果
3
true
2
name=ZhangSan, id=1
name=WangWu, id=3
这里可以看出已经删除成功
————————————————————————————————————————————————————————
注意: 在List中存入不同的对象的时候,需要在被重写的equals方法中使用instanceof判断两个对象是否有子父类关系,否则会出现类型转换异常。
例如 这里再新建一个 Dog类,
public class Dog {
public String id;
public Dog(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
在list中添加Dog对象
List<Object> list = new ArrayList<Object>();
Person p1 = new Person("ZhangSan","1");
Person p2 = new Person("LiSi","2");
Person p3 = new Person("WangWu","3");
// 创建并添加Dog对象
Dog dog = new Dog("1");
list.add(dog);
list.add(p1);
list.add(p2);
list.add(p3);
// 删除前元素的个数
System.out.println(list.size());
System.out.println(list.remove(new Person("LiSi","2")));
// 删除后元素的个数
System.out.println(list.size());
执行之后则会报异常
4
Exception in thread "main" java.lang.ClassCastException: com.xingtang.test1.Dog cannot be cast to com.xingtang.test1.Person
at com.xingtang.test1.Person.equals(Person.java:35)
at java.util.ArrayList.remove(Unknown Source)
at com.xingtang.test1.Test.main(Test.java:38)
这里先输出未删除的时候集合的长度
但执行到remove()方法的时候,需要遍历集合,要把集合中每个元素的对象传入到equals()方法中,而重写的equals方法中将传入的对象强制转换为(向下转型)为Person类型,当遍历到List中的第一个元素的时候因为这里存的是Dog对象和Person并没有子父类的关系,直接进行类型转换就会报类型转换异常ClassCastException。当然如果在将要删除的元素之后添加Dog对象就不会报异常,因为ArrayList是有序的,当遍历到将要删除的对象的时候这时会直接将元素删除并使用return结束了方法,也就不会对和Dog对象进行比较,那么也就不会出现类型转换异常了,但是当对Dog对象后的元素进行删除的时候仍会报异常
这里如果在Person类中的equals方法中进行一次instandsof判断就可以很好的解决这个问题
在Person的equals()方法中添加代码
@Override
public boolean equals(Object obj) {
if(obj instanceof Person) {
Person person = (Person)obj;
return (this.id.equals(person.getId())
&& this.name.equals(person.getName()));
}else{
return false;
}
再次运行测试类就不会报错了
4
true
3
对于Dog类也是一样的需要在重写的equals()方法中对传入的对象进行子父类判断,其方法和Person类似。