简述contains的底层实现
举例String的contains底层:
main方法:
List<String> names= new ArrayList<>();
names.add("Jimmy");
System.out.println(names.contains("Jimmy"));
contains源码:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
immy传入到contains方法中的参数,即o指向Jimmy所指向的对象,o为上转型对象
indexof 源码:
public int indexOf(Object o) {
if (o == 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]))
return i;
}
return -1;
}
indexof方法流程:判断o是否为null。如果是null,则循环if(jimmy ==null),如果找到,将index赋值为找到的地址,则返回index。
因为Jimmy不是null,则for循环遍历names中每一个元素;其中size为全局变量,实质为this.size,意思是names的元素个数。让Jimmy和数组中的每一个元素进行比较。如果找到,返回i下标,则返回index。找不到就返回-1。
由题知,names为一个上转型对象,运行时会调用ArrayList里的已有的equals方法。
string的equal源码
public boolean equals(Object anObject) {
if (this == anObject) {// 如果是同一个对象,返回true
return true;
}
if (anObject instanceof String) { // 判断是否是string对象
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {// 判断长度是否一致
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n != 0) {
if (v1[i] != v2[i])// 比较每个字符是否一样
return false;
i++;
}
return true;
}
}
return false;
}
ArrayList里的equals方法流程:1.判断与Jimmy比较的name中的元素的类型是否为String或者子类,如果不同,则返回false,如果相同,执行String的equals。
因为String的equals只判断字符是否相同,所以输出结果为true。
举例自定义的contains底层:
定义student:
public class Student {
String id;
@Override
public Student(String id) {
super();
this.id = id;
}
main方法:
List<Student> list = new ArrayList<>();
list.add(new Student("110"));
System.out.println(list.contains(new Student("110")));
contains源码:
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
new Student("110")传入到contains方法中的参数,即指向new Student("110")所指向的对象,new Student("110")为上转型对象
indexof源码:
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;
}
object的equals的源码:
public boolean equals(Object obj) {
return (this == obj);
}
因为如果运行上图,因为Student没有equals方法,则会调用object的equals方法,object比较地址是否相同,不能很好的实现我们想要的结果,使用需要重写Student的equals方法。
重写equals方法:
public boolean equals(Object obj) {
if (obj instanceof Student) {
Student student = (Student) obj;
return this.id.equals(student.id);
}
return false;
}
这里obj是一个上转型对象,将new Student("110")判断是否为Student,如果没有这步,这可能出现类型转化错误,然后将obj下转型,这样才能调用Student的方法。最后将names的值的id和110进行比较,返回一个true或者flase。