详述:ArrayList类contains方法

源码

public boolean contains(Object o) {
        return indexOf(o) >= 0;
 }
public int indexOf(Object o) {
        return indexOfRange(o, 0, size);
    }

    int indexOfRange(Object o, int start, int end) {
        Object[] es = elementData;
        if (o == null) {
            for (int i = start; i < end; i++) {
                if (es[i] == null) {
                    return i;
                }
            }
        } else {
            for (int i = start; i < end; i++) {
                if (o.equals(es[i])) {
                    return i;
                }
            }
        }
        return -1;
}

1、String类型

ArrayList<String> names = new ArrayList<String>();
names.add("Jim");
System.out.println(names.contains("Jim"));

1.1、String类的分析方法

这个时候contains方法会执行第一个源码中的位置,接着返回方法indexof返回第二块源码位置,因为显然我们传入了一个值,“Jim”,这个值就是o,这时这个o显然不为null,所以代码会执行else对应的代码块es[i]代表了集合中的所有元素,拿o也就是“Jim”于集合中的元素比较,这时候就会调用equasls方法。判断内容是否一样,所以返回true。
这里值得注意的是:如果contains传入的数据是String数据类型的对象,则contains方法本质上调用的是String对象中的equasls方法

2、包装类类型

ArrayList<Integer> age = new ArrayList<Integer>();
age.add(111);
System.out.println(age.contains(new Integer(111)));

2.1、包装类类型的分析方法

这个时候o就是12了,这个时候equals方法调用的是Integer中的equals方法,比较的值是否会相等,则明显12=12,返回true。

//Integer中的equals方法
public boolean equals(Object obj){
	if(obj instanceof Integer){
		return value == ((Integer)obj).intValue();
	}
	return false;
}

3、自定义类类型

先创建一个学生类

//学生类
public class Student {

	private String id;

	public Student(String id) {
		this.id = id;
	}
}
	1 ArrayList<Student> students = new ArrayList<Student>();
	2 students.add(new Student("1111"));
	3 System.out.println(students.contains(new Student("1111")));
//Object类中equals方法
public boolean equals(Object obj){
	return (this==obj);
}
  • 分析
    这个时候就不能进行判断这个集合中是否含有Student对象了,因为当时学生对象时,那么源码中的o就是Student对象,要进行时,需要调用equals方法,因为学生类中没有equasl方法,就会调用父类(Object)类中的equals方法,这时候比较的是地址是否相等,显然代码students.add(new Student("1111"));和代码System.out.println(students.contains(new Student("1111")));中是两个不同的对象(两个new),所以会返回false。

3.1、如何解决类类型中无法比较的问题?

  • 重写equals方法
//重写equals方法后的学生类
public class Student {

	private String id;

	public Student(String id) {
		this.id = id;
	}

	@Override
	public boolean equals(Object obj) {
		Student s = (Student) obj; 
		return this.id.equals(s.id);
	}
}

当执行到equasl方法时,会调用我们在Student类中重写的equals方法,因为obj中是一个Object类型的变量,当我们进行学生类的比较时,我们应该先将obj下转型(强制类型转换),也就是我们要传入的变量,也就是代码students.add(new Student("1111"));中的new Student对象。而在源码中,是o去调用equals方法,this指的就是o,返回内容是否相等,所以为true。

3.2、为什么重写之后需要加instanceof?

如果我们就像上面那样重写equasl方法,会发现一个问题,比如下面代码:

ArrayList<Object> list = new ArrayList<Object>();
list.add(new String("1111"));
System.out.println(list.contains(new Student("1111")));

发现执行上诉代码时,会出现异常,因为String类型是不可能强制类型转换成学生类的,所以我们要加上instanceof。
因为string类型没有可比性,所以如果传入的对象不是学生类,就直接返回false。

//改良后重写equals方法的学生类
public class Student {

	private String id;

	public Student(String id) {
		this.id = id;
	}

	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Student) {
			
			Student s = (Student) obj; 
			return this.id.equals(s.id);
		}
		return false;
	}

	
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值