详述ArrayList类中的contains方法(Java:集合与泛型(五))
一、源码:
ArrayList类中的contains方法源代码如下:
①当ArrayList调用contains方法时代码如下:
②执行contains方法时会执行indexOf方法:
③indexOf方法的具体内容为:
二、当<>中泛型为String时:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
ArrayList<String> names = new ArrayList<String>();
names.add("Tom");
System.out.println(names.contains("Tom"));
}
}
分析:根据上述源码可知,当names执行contains方法时,会执行indexOf方法,此时indexOf方法获得的实际参数为“Tom”(不为null),因此此时会对ArrayList中的元素进行遍历,并依次与实际参数“Tom”进行比较(比较方法是equals方法),我们可以通过debug模式找出此时调用的equals方法为String类中的equals方法,当找到与实际参数“Tom”相同的ArrayList元素时,indexOf返回值为i,此时contains方法的返回值为ture,否则为false。
三、当<>中泛型为包装类时(以Integer为例):
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> scores = new ArrayList<Integer>();
scores.add(99);
System.out.println(scores.contains(99));
}
}
分析:根据上述源码可知,当scores执行contains方法时,会执行indexOf方法,此时indexOf方法获得的实际参数为99(不为null),因此此时会对ArrayList中的元素进行遍历,并依次与实际参数99进行比较(比较方法是equals方法),我们可以通过debug模式找出此时调用的equals方法为Integer类中的equals方法,当找到与实际参数99相同的ArrayList元素时,indexOf返回值为i,此时contains方法的返回值为ture,否则为false。
--------------------------Integer类中的equals方法如下--------------------------
四、当<>中泛型为 自定义类型时:
我们首先定义好一个自定义Student类:
public class Student {
public String name;
public Student(String name) {
this.name=name;
}
}
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
ArrayList<Student> stus = new ArrayList<Student>();
stus.add(new Student("Jim"));
System.out.println(stus.contains(new Student("Jim")));
}
}
分析:根据上述源码可知,当stus执行contains方法时,会执行indexOf方法,此时indexOf方法获得的实际参数为new Student(“Jim”)(不为null,并且为上转型对象),因此此时会对ArrayList中的元素进行遍历,并依次与实际参数new Student(“Jim”)进行比较(比较方法是equals方法),由于Student类中并没有重写Object父类中的equals方法,此时实际参数new Student(“Jim”)只能调用Object中的equals方法,而由源代码可知:该equals方法比较的时对象的地址,因此此处输出为false。
Object中equals方法如下:
为改进这一异常,我们可以通过对String和Integer中的分析中得到启发:在自定义类Student中重写equals方法,改进的代码如下:
public class Student {
public String name;
public Student(String name) {
this.name=name;
}
@Override
public boolean equals(Object obj) {
Student s = (Student)obj;
String elementName = this.name;
String targetName = s.name;
if(elementName.equals(targetName)) {
return true;
}else {
return false;
}
}
}
此时执行 System.out.println(stus.contains(new Student(“Jim”))); 该行代码时的运行结果为true,但代码仍然不足:
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
ArrayList<Object> stus = new ArrayList<Object>();
stus.add(new String("Jim"));
System.out.println(stus.contains(new Student("Jim")));
}
}
此时运行控制台会给出如下异常信息:
ClassCastException为类型转换异常:当String对象转换为Student类型对象会发生该异常,我们根据Integer中重写的equals方法可得到启发并将代码改进如下:
public class Student {
public String name;
public Student(String name) {
this.name=name;
}
@Override
public boolean equals(Object obj) {
if(obj instanceof Student) {
Student s = (Student)obj;
String elementName = this.name;
String targetName = s.name;
if(elementName.equals(targetName)) {
return true;
}else {
return false;
}
}else {
return false;
}
}
}
注:我们在原来的代码基础上增添了类型判断,如果此时equals中传进来的实际参数不为Student类型,则直接返回false,这样就避免了类型转换异常这样的错误。
上一篇: about android screen
下一篇: 集合框架和泛型——JAVA