HashMap、HashTable、HashSet 布满荆棘的人生 2022-05-13 04:30 203阅读 0赞 # 关于HashMap # 首先要清楚HashMap的存储结构,如下图所示: ![70][] 图中,紫色部分即代表哈希表,也称为哈希数组,数组的每个元素都是一个单链表的头节点,**链表是用来解决冲突的,**如果不同的key映射到了数组的同一位置处,就将其放入单链表中。 **HashMap**是**非synchronized**,而**Hashtable是synchronized**,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。 **sychronized意味着在一次仅有一个线程能够更改Hashtable。就是说任何线程要更新Hashtable时要首先获得同步锁,其它线程要等到同步锁被释放之后才能再次获得同步锁更新Hashtable。** **HashMap**是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。 HashMap 实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆。 ## HashMap和HashSet的区别: ## ![70 1][] ## 什么是Hash? ## Hash:**是一种信息摘要[算法][Link 1]**,它还叫做哈希,或者散列。我们平时使用的MD5,SHA1都属于Hash算法,通过输入key进行Hash计算,就可以获取key的HashCode(),比如我们通过校验MD5来验证文件的完整性。 对于HashCode,它是一个本地方法,实质就是地址取样运算 碰撞:好的Hash算法可以出计算几乎出独一无二的HashCode,如果出现了重复的hashCode,就称作碰撞; 就算是MD5这样优秀的算法也会发生碰撞,即两个不同的key也有可能生成相同的MD5。 ## 如果两个键的hashcode相同,你如何获取值对象? ## 当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,找到bucket位置之后,会调用keys.equals()方法去找到链表中正确的节点,最终找到要找的值对象。HashMap的底层实现是链表。 ## **能否让HashMap实现线程安全,如何做?** ## 1、直接使用Hashtable,但是当一个线程访问HashTable的同步方法时,其他线程如果也要访问同步方法,会被阻塞住。举个例子,当一个线程使用put方法时,另一个线程不但不可以使用put方法,连get方法都不可以,效率很低,现在基本不会选择它了。 2、HashMap可以通过下面的语句进行同步: Collections.synchronizeMap(hashMap); 3、直接使用JDK 5 之后的 ConcurrentHashMap,如果使用Java 5或以上的话,请使用ConcurrentHashMap。 [70]: /images/20220513/e235ac23f4e444f7a4f255df35bf691f.png [70 1]: /images/20220513/036814a270a545fda4344060e79955ce.png [Link 1]: http://www.java123.net/v/list-192-1.html
还没有评论,来说两句吧...