详述ArrayList类中的contains方法
一、contains方法的参数是String类型
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<String> nameList = new ArrayList<>();//JDK7.0即以上版本创建对象尖括号里的泛型可以省略
nameList.add("Tom");
String name = "Tom";
System.out.println(nameList.contains(name));//思考:contains方法如何执行
}
}
程序运行结果:
contains()方法的源代码:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
name是String类型的变量,指向“Tom”对象。name作为contains的参数传给变量o。因为变量o是Object类型的变量,但它指向的却是String类型的对象“Tom”,所以变量o指向的对象“Tom”是一个上转型对象。在contains()方法,将o作为参数调用indexof()方法。如果indexof()方法的返回值大于等于0,则返回true,集合中存在该元素。否则,返回false,集合中不存在该元素。
indexof()的源代码:
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
变量o指向的对象仍然是上转型对象“Tom”。if语句的判断条件“o == null”显然不成立,因此执行else语句。在else语句中f使用or循环遍历namelist集合 。在循环体中执行if语句,调用equals()方法,将集合中的元素与o指向的对象一个一个对比,如果相等则返回集合中与之相等元素的索引。for循环执行完都没找到相等元素,则返回-1。
注意:因为o指向的是上转型对象,所以调用equal()方法时,表面上执行的是Object类中的equals方法,实质上执行的是该上转型对象对应类中的equals()方法,在该程序中既是String类中的equals()方法。
执行该程序时,集合namelist中显然存在对象Tom,因此indexof()方法的返回值是0,所以contains()方法的返回值是true。
二、contains方法的参数是null
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<String> nameList = new ArrayList<>();
nameList.add("Tom");
System.out.println(nameList.contains(null));//思考:contains方法如何执行
}
}
程序运行结果:
contains()方法源代码:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
变量o指向的对象为null。在contains()方法中调用indexof()方法。
indexof()方法源代码:
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
变量o指向的对象为null,“o == null”结果为true,因此执行if语句。if语句中通过for循环遍历该集合,如果集合中有元素等于null,则返回该元素的索引。for循环执行完毕仍未找到元素等于null,则返回-1。
该程序中,namelist集合中没有元素null,因此indexof()方法的返回结果是-1,-1<0,所以contains()方法的返回结果是false。
三、contains方法的参数是其它类型(以Student类为例)
1、未重写Student类里的equals方法
public class Student {
private String stuNo;
private String name;
public String getStuNo() {
return stuNo;
}
public void setStuNo(String stuNo) {
this.stuNo = stuNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(String stuNo, String name) {
this.stuNo = stuNo;
this.name = name;
}
}
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Student> studentList = new ArrayList<>();
Student student1 = new Student("110","Tom");
Student student2 = new Student("110","Tom");
nameList.add(student1);
boolean flag = studentList.contains(student2);
System.out.println(flag);
}
}
程序运行结果:
contains()方法源代码:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
indexof()方法源代码:
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
如上述分析,变量o指向上转型对象student1。contains方法调用indexof方法,在indexof方法中执行else语句,通过for循环遍历studentList集合,将集合中的元素和变量o里的对象通过equals方法一一比较。因为变量o指向的上转型对象类型是Student类型,所以调用的是Student类里的equals方法。又因为Student类没有重写equals方法,所以调用的还是Object类中的equals方法。Object类中的equals方法比较的是两个对象的地址,Student1和Student2的的值显然不一样,所以indexof方法返回-1,contains方法返回false。
2、重写了Student类里的equals方法
public class Student {
private String stuNo;
private String name;
public String getStuNo() {
return stuNo;
}
public void setStuNo(String stuNo) {
this.stuNo = stuNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(String stuNo, String name) {
this.stuNo = stuNo;
this.name = name;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Student) {
Student student = (Student)obj;
return this.getStuNo().equals(student.getStuNo());
}else {
return false;
}
}
}
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Student> nameList = new ArrayList<>();
Student student1 = new Student("110","Tom");
Student student2 = new Student("110","Tom");
nameList.add(student1);
boolean flag = nameList.contains(student2);
System.out.println(flag);
}
}
程序运行结果:
Student类中重写equals方法,首先判断equals方法的参数对象是不是Student类或是其子类,如果不是直接返回false,如果是则执行下转型,将Object类型转为Student类。然后通过调用String类中的equals方法比较这两个Student 对象的stuNo属性,相等返回true,否则返回false。
重写Student类的equals方法之后,在方法indexof中调用equals方法时,将调用Student本类中的equals方法,这时比较的不是两个对象的地址,实质上是调用String类中的equals方法比较两个Student对象的stuNo属性。因为Student1和Student2中的stuNo属性都是“110”,所以indexof方法返回0,contains方法返回true。