Java之详述ArrayList类中contains方法

源码

public boolean contains(Object o) {//参数上转型
	return indexOf(o) >= 0;//调用下面indexOf方法
}

public int indexOf(Object o) {
	if (o == null) {//如果是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]))//参数o调用equals方法与ArrayList集合各个元素进行比较
				return i;
	}
	return -1;
}

泛型为String类型时

import java.util.ArrayList;

public class Test {

	public static void main(String[] args) {
		//String类
		ArrayList<String> names = new ArrayList<String>();
		names.add("Jim");
		System.out.println(names.contains("Jim"));//判断是否包含某个元素
	}
}

代码分析:

  1. 泛型为String类型的ArrayList集合names首先调用contains方法,同时待比较的字符串"Jim"传到contains的参数上并进行上转型变成Object类型;
  2. 调用indexOf方法并将参数o传给indexOf方法的参数o;
  3. 判断不是null,进入else语句,再由参数o调用其equals方法,并将集合names中的每一个元素当做参数传给equals方法;
  4. 由于o为String类型的上转型对象,并且String类型中已经对equals进行了重写,所以在执行时会调用String类型中的equals方法,对字符串进行比较
  5. 最终如果找到了相同的字符串,则返回这个元素在ArrayList中的位置;否则返回-1;
  6. 再回到contains方法中,如果indexOf返回的是-1,则返回false;如果返回的是个非负整数,则返回这个数,即找到的相同元素(字符串)的位置。

泛型为包装类时

import java.util.ArrayList;

public class Test {

	public static void main(String[] args) {
		//包装类
		ArrayList<Integer> ages = new ArrayList<Integer>();
		ages.add(12);
		System.out.println(ages.contains(12));
	}
}

代码分析:

  1. 泛型为Integer类型的ArrayList集合ages首先调用contains方法,同时待比较的整型12传到contains的参数上并进行上转型变成Object类型;
  2. 调用indexOf方法并将参数o传给indexOf方法的参数o;
  3. 判断不是null,进入else语句,再由参数o调用其equals方法,并将集合names中的每一个元素当做参数传给equals方法;
  4. 由于o为Integer类型的上转型对象,并且Integer类型中已经对equals进行了重写,所以在执行时会调用Integer类型中的equals方法,对整型进行比较
  5. 最终如果找到了相同值的整型,则返回这个元素在ArrayList中的位置;否则返回-1;
  6. 再回到contains方法中,如果indexOf返回的是-1,则返回false;如果返回的是个非负整数,则返回这个数,即找到的相同元素(整型)的位置。

泛型为自定义类型时

import java.util.ArrayList;

public class Test {

	public static void main(String[] args) {
		//自定义类
		ArrayList<Student> students = new ArrayList<Student>();
		students.add(new Student("111"));
		System.out.println(students.contains(new Student("111")));
	}
}

当Student类中未重写equals方法时:

public class Student {
	String id;	
	public Student(String id) {//构造方法
		this.id=id;
	}
}

分析:

  • 此时所有步骤和之前的大致一样,但调用equals方法时调用的是Object类中的equals方法
  • 故会对二者的地址进行比较
  • 显而易见二者的地址一定不同,即使二者学号相同,在我们看来是同一个学生,但由于存储的地址不同,最终返回的一定是false
  • 从而造成了判断错误

当Student类中重写equals方法时:

public class Student {

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

	@Override
	public boolean equals(Object obj) {//重写equals方法
			Student stu = (Student)obj;//将obj下转型,才能调用新增的id属性
			return this.id.equals(stu.id);			
	}
}

分析:

  • 此时重写了Object中的equals方法后,和String类与包装类一样,此时会调用Student类中重写的euqals方法
  • 但由于equals方法中参数obj是上转型对象,无法掉用Student中新增的属性id,故要想比较id,必须先对其进行下转型
  • 从而最终做到比较学生的id是否相同,而非地址

但当出现下面情况时会报错:

import java.util.ArrayList;

public class Test {

	public static void main(String[] args) {	
		//自定义类	
		ArrayList<Object> list = new ArrayList<Object>();//此时集合中可以放任何对象
		list.add(new String("111"));
		System.out.println(list.contains(new Student("111")));
	}
}
  • 由于是String对象调用contains方法,传入参数为Student对象
  • 故当调用equals方法时,由Student对象调用其equals方法,并将String对象当做参数传给equals方法中
  • 此时会将String对象强制转换为Student对象,于是报错

解决方法:使用instanceof关键字

public class Student {

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

	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Student) {//集合中可能存的未必是Student类创建的对象
			Student stu = (Student)obj;
			return this.id.equals(stu.id);			
		}
		return false; 
	}
}

分析:

  • 当集合中不是Student类创建的对象时,调用equals方法时便会直接返回false
  • 从而解决了非Studnet类导致的报错问题
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值