Arraylist中contains方法底层实现解读与HashSet自定义类型去重效果的简述(接上一篇)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,就可以实现判断自定义类型中判断某位元素相同,从而达到去重效果,不像不重写之前都会添加进去的漏洞。

以上是关于Arraylist中contains方法底层实现解读与HashSet自定义类型去重效果的简述(接上一篇)的主要内容,如果未能解决你的问题,请参考以下文章

ArrayLiist类中的contains()方法底层依赖的是equals()方法

Java通过ArrayList的contains(Object o)方法实现去重字符串中的字符

ArrayList 源码(基于Java1.8)

java集合

HashSet的contains()和ArrayList的contains()方法哪个更快一些?

ArrayList 从源码角度剖析底层原理