简述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;
}
J
```

immy传入到contains方法中的参数,即o指向Jimmy所指向的对象,Jimmy为上转型对象

#### 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方法流程:判断jimmy是否为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;
}
J
```

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。

上一篇:[UnexpectedValueException] Your github oauth token for github.com contains invalid characters


下一篇:C#中Linq的Join比Where(m=>arr..Contains(m.id))的效率更高