Arraylist中contains方法底层实现解读与HashSet自定义类型去重效果的简述(接上一篇)
Arraylist中contains方法底层实现解读(接上一篇)
上一篇最后提到Arraylist中contains方法里面有用到equals方法的地方,而且在自定义类中,如果不重写equals方法会导致就算一样也会false,所以这次我们来解决这个问题。首先我们现看Arraylist中contains方法里面有用到equals方法的地方:
int indexOfRange(Object o, int start, int end) {//o为传进来要比较的元素或自定义对象,start为0,end为Arraylist元素个数
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])) { //传进的元素或对象与es数组中各个元素或者对象比较,若为String类型则调用 String中equals方法进行判断,若为自定类型,则调用Object中equals方 法进行判断,下面将详细介绍比较原理。
return i; //若通过判断则返回下标。也就是最后返回true,表示含有改元素或对象。
}
}
}
return -1;
}
String类型equals比较原理:
String a = "aa";
String str = new String("aa");
"a".equals("a");
System.out.println(a==str);
public boolean equals(Object anObject) {
if (this == anObject) {//一个String类型元素调用,则this就为该元素,传进来的参数是后边"a",首先比较两个元素的内存地址,相等就返回true,一般不像str那样new对象的话,一般都会指向常量池统一内存地址,直接返回true,若new了新对象,则不进入本语句,进入下一个下一个判断语句
return true;
}
if (anObject instanceof String) {//判断类型是否为String类型若是则进入,不是则返回false,不用比了,类型不同,根本不会想等。
String aString = (String)anObject;//下转型转为String类型
if (!COMPACT_STRINGS || this.coder == aString.coder) {//常量COMPACT_STRINGS为flase,短路语句直接进入语句体
return StringLatin1.equals(value, aString.value);//此时返回一个东西,这时我们要点进这个equals看具体方法。在下一个代码块内介绍
}
}
return false;
}
public static boolean equals(byte[] value, byte[] other) {//里面两个形参 传进两个要比较的元素,放到byte数组里
if (value.length == other.length) {//先比较两个数组的长度 如果长度不同 就不会进入
for (int i = 0; i < value.length; i++) {//进入循环
if (value[i] != other[i]) {//“aa”被拆分放到byte数组里一个一个字母比较,不像等返回false,否则返回true。
return false;
}
}
return true;
}
return false;
}
至此String中equals比较结束,在例子中返回true。
自定义类中的equals方法
List<Student> list = new ArrayList<Student>();
Arraylist中contains中equals方法,
因为自定义类Student中没重写Object中equals方法,则调用Object中equals方法:
public boolean equals(Object obj) {
return (this == obj);
}
没次都比较地址值,因为Student存入都要新的对象,所以,每次都不想等,所以每次都会返回false,所以会干扰到我们正常比较所以我们就需要重写equals方法:
public boolean equals(Object obj) {
if(obj instanceof Student) {//可以首先判断是否为同一个自定类型,不同返回false
Student student = (Student)obj;//转为Student类型
return this.id.equals(student.id);//这里为自定类型中某一元素比较是否相同,相同为false,所以这样可以解决总是为false的问题。
}
return false;
}
以上可以用到set的add中,原理相同,不重写的话没有去重效果,HashSet真想实现自定义类型去重效果,还需要重写HashCode,就可以实现判断自定义类型中判断某位元素相同,从而达到去重效果,不像不重写之前都会添加进去的漏洞。