欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

详述ArrayList类中的contains方法(Java:集合与泛型(五))

程序员文章站 2022-05-23 14:18:35
...

一、源码:

ArrayList类中的contains方法源代码如下:

①当ArrayList调用contains方法时代码如下:
详述ArrayList类中的contains方法(Java:集合与泛型(五))
②执行contains方法时会执行indexOf方法:
详述ArrayList类中的contains方法(Java:集合与泛型(五))
③indexOf方法的具体内容为:
详述ArrayList类中的contains方法(Java:集合与泛型(五))

二、当<>中泛型为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方法如下--------------------------
详述ArrayList类中的contains方法(Java:集合与泛型(五))

四、当<>中泛型为 自定义类型时:

我们首先定义好一个自定义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方法如下:
详述ArrayList类中的contains方法(Java:集合与泛型(五))
为改进这一异常,我们可以通过对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")));	
	}
}

此时运行控制台会给出如下异常信息:
详述ArrayList类中的contains方法(Java:集合与泛型(五))
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,这样就避免了类型转换异常这样的错误。