hashset的底层是hashmap,hashmap的底层是节点数组+链表+红黑树。
首先每个节点有四个元素。
第一个为hash值,相当于索引(放在数组的位置,或者理解为桶位置)。
第二个为key,就是你要存的对象,第三个为共享对象(固定的一个对象)【只起到占位】,第四个为指针,指向下一个节点。
首先刚new hashmap时创建一个空数组table,当放第一个元素时进行扩容,第一次扩容16个,扩容因子为0.75(固定)。每当添加的元素个数超过当前数组个数 * 扩容因子时触发扩容,扩容为之前的2倍。第二次触发时就是当map中元素个数超过12个就进行扩容。【注意,这个并不是占用数组个数,而是节点个数】。
而当hash值(这里的hash值,不是hashcode,需要hashcode进行亦或右移十六位如 : h ^ (h>>>16),为的是尽量得到不同的hash值)相同时,可能会放在同一条链表上,先比较地址是否相同,如果相同则不添加,如果不相同,则通过equals(equals可以由程序员自己自定义)判断内容是否相同。如果相同则不添加,如果不同则与下一个节点进行比较。当地址不相同并且值不相同,则添加到链表的最后。
链表触发的扩容与转化,当其中一条链表已经有8个节点后,当又要在这条链表上添加第九个节点时,首先会判断是否数组长度是否达到64个,如果没有则进行扩容。扩容后会有一个新的hash值,也就是某一条链表上有9个节点。而当数组长度为64且有一条链表长度超过8个,则将该条链表转化为一颗红黑树。
table表不会无限扩容,有一个最大值maxvalue。
下面是重写hashcode和equals