在java中,contains方法用于判断集合中是否包含某个元素,包含则返回true,否则返回false。
boolean contains(Object o); //
先看一个案例:字符串str实际上没添加进集合c里,但是contains返回的结果却是true?也就是说,contains发现str包含在c集合里。
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//添加数据
c.add("abc");
c.add(123);
//1.str实际上没添加进集合c里,但是contains返回的结果却是true?
String str = "abc";
System.out.println("str是否包含在集合里:"+c.contains(str)); //true
再看第二个案例:new了两个属性相同的学生对象stu1和stu2。跟代码一逻辑一样,把stu1添加进集合里,因为两个学生的名字是相同的,所以用contains方法比较stu2是否包含在集合c里,然而这次返回结果是false,为什么,明明两个学生名字一样啊。
public static void main(String[] args) {
//创建集合对象
Collection c = new ArrayList();
//添加数据
c.add("abc");
c.add(123);
//2.根据上面的逻辑,这次new两个属性相同的学生对象stu1和stu2,把stu1添加进集合里,然后判断stu2是否在集合里,这次结果为false
Student stu1 = new Student("小明");
Student stu2 = new Student("小明");
c.add(stu1);
System.out.println("学生对象stu是否在集合c里:"+c.contains(stu2)); //false
}
}
//学生类
class Student{
String name;
//带参构造方法
public Student(String name) {
this.name = name;
}
原因:
通过查看实现类ArrayList里的contains方法可以发现,从contains()到indexOf(),再到indexOfRange(),在最后的indexOfRange()方法里,调用了equals()方法来进行比较。
//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;
}
结论分析
关于equals方法,我们得知道,所有的子类默认继承Object类,而Object的equels方法只是返回对象内存地址。
由此分析代码一:集合里有一个字符串“abc”,创建一个String变量赋值“abc”,两者本质上都是字符串,且String类型已经重写equals方法。contains在对两个比较的时候调用的是equals方法,由于String类的已经重写了,返回的是属性而不是内存地址,故字符串可以被正确比较。
代码二分析:虽然两个学生的名字属性一样,但是,集合保存的是对象的内存地址,而Student类没有重写equals方法,所以contains方法在调用equals方法判断的时候,判断的是两个对象的地址,两个对象的内存地址肯定不一样,所以返回false。
代码二解决方案:重写Student的equals方法,使其返回对象属性,即可获取正确的判断。
//学生类重写的equals方法
class Student{
String name;
public Student(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Student)) return false;
if(obj == this) return true;
Student s = (Student) obj;
if(this.name == s.name) return true;
return false;
}
}
再看以下代码:
Integer x = 1000;
Integer y = 1000;
c.add(x);
System.out.println(c.contains(y)); //true
虽然new了两个不一样的对象,但是Integer包装类重写了equals方法,所以x和y是一样的。
结论:放在集合里的类型,一定要重写equals方法。
注意:remove删除方法也是调用的equals方法。
评论 (0)