先谈谈如何让元素不重复:
利用equals()将要存储的与已有的逐个进行比较。
缺点:效率会大大降低。
再谈谈HashMap集合中使用的不重复判定方式:
先清楚一个概念,
HashMap集合的K值只能是以对象形式传入,例如:String,Integer,等等包装类的形式。
为什么呢?
因为包装类都重写了HashCode方法和equals方法。而这两个方法与不重复有着密切联系。
再谈谈HashMap集合的结构:
底层是哈希表,
由,一条数组+链表/红黑树组成。
数组名字叫:table,它用做存储K值的哈希值。
假如,此时有一个K值传入,会先计算 K的哈希值,然后与集合中的全部 哈希值 比较 如果不相同,则存储进来。如果哈希值有相同的,则会将全部相同哈希值的K值进行equals比较。 如果equals比较结果是不同,则存储进来。如果相同,则代表是相同对象,则不会进行存储。
由此产生的结果:
1、如果有相同哈希值的元素小于8个,那么这些数会以链表的形式挂在数组中对应的哈希值下面。
2、如果相同哈希值的元素大于 8个,则会从链表形式转换为红黑树形式挂在后面。(8个后红黑树效率更高)
3、确实会存在哈希值相同但是equals比较结果不同。
- 原因:HashCode方法返回的是int值,更多地是有属于自己的 计算方法,既然是计算,那么就是有逻辑的,有规律的,是动态的,可变的。那么就有可能很不巧的两个不同对象计算出来的哈希值相同。
- 反观 equals方法 不重写前是直接比较的地址,它是死的,只有相同对象的地址相同,即使重写了,如果是String比较的还是地址,如果是char、int 就是字符、数字 能直接==比较
- 由此可见,确实是会出现hashcode相同但是equals不同的情况,而equals才是判断两个对象是否相同的方法。
4、 HashCode方法的效率要高于equals。
ps:
- 包装类Integer的哈希值是变量值的本身,即
那么哈希值就是 123。Integer a = 123;
- 重写hashcode后char类型的属性的hashcode值是直接将字符转换为int类型就输出。