ArrayList底层实现contains⽅法的原理。
List实现类ArrayList底层实现contains()的原理
实验代码
List<String> names= new ArrayList<>();
names.add("Jimmy");
names.add("tommy");
System.out.ains("Jimmy")); //查询是否包含“Jimmy”
contains()源码
public boolean contains(Object o) {//此处的o即为contains⽅法中的参数对象,此处指“Jimmy”,o中存储上转型对象
return indexOf(o) >= 0;//数值>=0,返回true
}
public int indexOf(Object o) {equals()方法
return indexOfRange(o, 0, size);//size指调⽤contains()的集合的⼤⼩
}
int indexOfRange(Object o, int start, int end) {
Object[] es = elementData; //将集合中元素放到数组中
if (o == null) {//o为null的情况
for (int i = start; i < end; i++) {//遍历集合中的元素,直到到集合中为null的元素为⽌
if (es[i] == null) {
return i;
}
}
} else {//!o == null
for (int i = start; i < end; i++) {//
if (o.equals(es[i])) {//o调⽤相应的equals()⽅法
return i;//返回到⽐较成功元素的下标
}
}
}
return -1;
}
上⾯o(continue⽅法中的参数对象)调⽤的什么样的equals()⽅法取决于o是什么类型:
contains()⽅法中的参数类型调⽤的equals()⽅法
String类型String对象中的equals⽅法
基本数据类型的包装类包装类中的equals()⽅法
类类型类类型中的equals()⽅法
分析实现代码的运⾏过程
1.当执⾏到names.add("Jimmy");时,调⽤contains()⽅法,其中“Jimmy”赋值给o,o即为String类。
2.接着再调⽤indexof()⽅法,返回indexofRange()⽅法,因为o ! = null;所以进⼊else{}语句⾥,o去调⽤String⾥⾯的equals()⽅法(先⽐较地址,再⽐较每个字符,有⼀样相同即返回true),与集合中的元素进⾏⽐较,⼀旦到相同的(即equals()⽅法返回true),则返回此时对应的i。
3.跳回contains()⽅法中,因此时 i>=0; 所以返回true。
⾃定义类类型
学⽣类
public class Student {
private String id;
public Student(String id) {
super();
this.id = id;
}
public Student() {
super();
}
}
测试类
List<Student> list = new ArrayList<>();
list.add(new Student("123"));
list.add(new Student("124"));
System.out.ains(new Student("123")));
分析实现代码的运⾏过程
这时候返回的值为: false.
1.执⾏到ains(new Student("123"))的时候,跳转到contains()⽅法,创建⼀个Student对象“123”赋值给o,o为Student类。
2.接着再调⽤indexof()⽅法,返回indexofRange()⽅法,因为o ! = null;所以进⼊else{}语句⾥,o本来要调⽤Student类⾥⾯的equals()⽅法,但是Student类⾥⾯没有重写equals()⽅法,所以只能调⽤⽗类Objecr类⾥⾯的equals()⽅法,⽽⽗类Objecr类⾥⾯的equals()⽅法⽐较的是地址,我们每创建⼀个对象都会新开辟⼀个空间,即每创建⼀个对象都有⼀个,因此o的地址与集合中的每个元素的地址不⼀样,所以equals()⽅法返回的为false,跳出else语句,执⾏return -1;。
3.跳转回contains()⽅法⾥,最终返回false。
4.所以我们想要让contains()⽅法成功,就必须在Student类中重写equals()⽅法。
重写equals()⽅法
public class Student {
private String id;
public Student(String id) {
super();
this.id = id;
}
public Student() {
super();
}
@Override
public boolean equals(Object obj) {//集合中的每⼀个元素
if(obj instanceof Student) {//判断输⼊的类型是否是属于Student
Student student = (Student)obj;//下转型对象,上⾯进⾏了上转型
return this.id.equals(student.id);//o的字符与集合中每⼀个元素的字符进⾏对⽐。
}
return false;
}
}
重写之后再运⾏,结果就为true了。再次分析⼀下:
1.执⾏到ains(new Student("123"))的时候,跳转到contains()⽅法,创建⼀个Student对象“123”赋值给o,o为Student类。
2.接着再调⽤indexof()⽅法,返回indexofRange()⽅法,因为o ! = null;所以进⼊else{}语句⾥,o调⽤Student类⾥⾯的equals()⽅法,我们重写的equals()⽅法先⽐较地址,再⽐较字符,有⼀个成⽴则返回true,条件满⾜进⼊if语句,执⾏return i;。
3.跳回contains()⽅法中,因此时 i>=0; 所以返回true。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论