`
wojiaolongyinong
  • 浏览: 73153 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

Hashtable和HashMap源码分析

阅读更多

Hashtable和HashMap源码分析

         JDK中自带的Hashtable和HashMap是数据结构中哈希表的实现。除了这两个,还有一个HashSet的实现,但是HashSet基本是基于HashMap实现的,因此在这里我们只讨论Hashtable和HashMap的实现细节。

         首先列出经过源码分析,得出的关于Hashtable和HashMap之间的异同点如下:

         1、Hashtable和HashMap的继承关系比较如下:

 


         其中没有列出它们两个继承的Cloneable和Serializable接口,在下面的分析也是一样,不会分析比较它们的序列化和Cloneable的实现。

 

          2、Hashtable和HashMap之间最为明显的区别:同步处理

                在Hashtable的实现中,所有的外部访问方法都进行了同步化处理,即在方法中添加synchronized关键字;

                Hashtable中的方法示例:

 

Java代码   收藏代码
  1. public synchronized V put(K key, V value) {  
  2.           
  3.      //此处省略内部实现  
  4. }  
  5.   
  6. public synchronized V remove(Object key) {  
  7.            
  8.      //此处省略内部实现  
  9. }  

                而在HashMap的实现中,没有进行同步化处理;

                HashMap中的同样两个方法示例:

 

Java代码   收藏代码
  1. public V put(K key, V value) {  
  2.     //此处省略内部实现  
  3. }  
  4.   
  5. public V remove(Object key) {  
  6.     //此处省略内部实现  
  7. }  

 

 

          3、Hashtable和HashMap关于输入的key和value的限制

          在Hashtable的实现中,不允许添加key或是value为null的键值对,如果key为null,则在put(K key,V value)方法调用hash()方法获取hash值时会抛出空指针异常, 而如果value为null,则在刚进入put(K key, V value)是就会检查而抛出空指针异常,如下具体程序所示:

 

         如下所示为Hashtable中的实现:

 

Java代码   收藏代码
  1. public synchronized V put(K key, V value) {  
  2.         // Make sure the value is not null  
  3.         if (value == null) {//在这里对value值进行了检验,如果为null,则抛出空指针异常  
  4.             throw new NullPointerException();  
  5.         }  
  6.   
  7.         // Makes sure the key is not already in the hashtable.  
  8.         Entry tab[] = table;  
  9.         int hash = hash(key);//在这里调用了下面的hash(Object k)方法  
  10.       
  11.     //在此省略了下面的实现......  
  12. }  
  13.   
  14. //在下面的方法中可以看出,只要传入的k值为null,则在下面调用时就会产生空指针异常  
  15. private int hash(Object k) {  
  16.         if (useAltHashing) {  
  17.             if (k.getClass() == String.class) {  
  18.                 return sun.misc.Hashing.stringHash32((String) k);  
  19.             } else {  
  20.                 int h = hashSeed ^ k.hashCode();  
  21.                 h ^= (h >>> 20) ^ (h >>> 12);  
  22.                 return h ^ (h >>> 7) ^ (h >>> 4);  
  23.              }  
  24.         } else  {  
  25.             return k.hashCode();  
  26.         }  
  27. }  

 

          而在HashMap的实现中,指定索引位置0处用来存放key值为null的键值对,如果在put方法中传入key值为null,如果索引位置0处存在已经存储的元素,则使用现在传进来的value值替换原来的value值,如果没有存储元素,则直接放置。所以我们容易知道,在HashMap中,键值key为null的键值对只能在索引位置为0的地方存储一个,即在整个HashMap中只允许有一个键值对的key为null,后面添加的只是在修改value值。

 

         如下所示为HashMap中的实现:

Java代码   收藏代码
  1. public V put(K key, V value) {  
  2.       if (key == null)  
  3.           return putForNullKey(value);  
  4.     //在这里省略了后面key不为null的实现  
  5. }  
  6.   
  7. //当key为null时调用  
  8. private V putForNullKey(V value) {  
  9.     for (Entry<K,V> e = table[0]; e != null; e = e.next) {  
  10.         //此时索引位置0处不为null,则替换原来的value值  
  11.       if (e.key == null) {  
  12.             V oldValue = e.value;  
  13.             e.value = value;  
  14.             e.recordAccess(this);  
  15.             return oldValue;  
  16.         }  
  17.     }  
  18.     modCount++;  
  19.     //索引位置0处为空,则将键值对放置进去  
  20.     addEntry(0null, value, 0);  
  21.     return null;  
  22. }  

        

        4、在Hashtable和HashMap中,在每一次添加元素时,都会检查此时表中已有的数据个数与临界值的大小关系,当已存入的数据个数大于等于threshold临界值时,Hashtable会调用rehash()方法来对数组进行扩充,HashMap会调用resize(int capacity)方法来对数组进行扩充,然后依次遍历原数组,重新计算元素的hash值,存储到新的数组中,而且两者都是将数组扩大一倍,其中的临界值threshold = loadFactor(装载因子,默认0.75) * capacity(数组大小);

 

         5、在Hashtable和HashMap中都提供了迭代器可让外部调用。在Hashtable和HashMap中均有entrySet()、keySet()、values()方法,分别返回Set<Entry<K,V>>、Set<K>、Collection<V>这三种类型的对象引用,其中就像上面说的,Hashtable返回的对象都是经过同步处理的,举个例子如下:

Java代码   收藏代码
  1. public Set<Map.Entry<K,V>> entrySet() {  
  2.     if (entrySet==null)  
  3.         entrySet = Collections.synchronizedSet(new EntrySet(), this);  
  4.     return entrySet;  
  5. }  

 而在HashMap中返回的对象引用,没有经过同步处理,举例如下:

Java代码   收藏代码
  1. public Set<Map.Entry<K,V>> entrySet() {  
  2.     return entrySet0();  
  3. }  
  4.   
  5. private Set<Map.Entry<K,V>> entrySet0() {  
  6.     Set<Map.Entry<K,V>> es = entrySet;  
  7.     return es != null ? es : (entrySet = new EntrySet());  
  8. }  
3
0
分享到:
评论

相关推荐

    HashMap与HashTable的区别(含源码分析)

    NULL 博文链接:https://qiaolevip.iteye.com/blog/2094447

    HashMap 源码分析

    是不是觉得很熟悉,没错这玩意在1.8之前的结构就和HashTable一样都是采用数组+链表,同样也是通过链地址法(这里简称拉链法)来解决冲突,但是HashMap和HashTable的区别是一个是线程安全的,一个是非线程安全的。...

    Java容器之Hashtable源码分析

    在上一篇博客 Java容器之HashMap源码分析(妈妈再也不用担心我不懂HashMap了) 从源码层次分析了HashMap容器的底层实现,在本篇博客将继续从源码层次分析Hashtable的底层实现。   注明:以下源码分析都是基于jdk ...

    Java集合框架源码剖析:HashSet 和 HashMap

     之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也是说HashSet里面有一个HashMap(适配器模式)。因此本文将重点分析HashMap。  HashMap实现了Map...

    java7hashmap源码-to-be-architect:成为Java架构师,你应该学习这些

    hashmap源码 to-be-architect to be a Java architect,you should learn these.This page is updated irregularly. Java基础 深入分析 Java SPI 机制和原理 并发编程专题 Executors线程池 线程池ThreadPoolExecutor...

    java8集合源码分析-Outline:大纲

    集合源码分析 JAVA: 基本语法 static 修饰变量 方法 静态块(初始化块 构造函数 ) 静态内部类() 静态导包 final() transient() foreach循环原理() volatile底层实现() equals和hashcode(, ) string,stringbuffer和...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    面试必考之HashMap源码分析与实现.mp4 │ │ │ ├─2.探索JVM底层奥秘ClassLoader源码分析与案例讲解 │ │ 2.探索JVM底层奥秘ClassLoader源码分析与案例讲解.wmv │ │ │ ├─3.锁、分布式锁、无锁实战全局性ID...

    java8集合源码分析-Petal:面试复习及面试经验

    集合源码分析 开发面试常见问题整理 算法题:这个一般不难,剑指offer或者LeetCode easy题目,喜欢考排序,链表,树(红黑树、二叉排序树、完全二叉树、B+树区别) Java基础:集合类、HashMap/HashTable/...

    免费下载:C语言难点分析整理.doc

    1. C 语言中的指针和内存泄漏 ...80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

    C语言难点分析整理.doc

    1. C 语言中的指针和内存...80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

    c语言难点分析整理,C语言

    目录 1. C 语言中的指针和内存...80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

    C语言难点分析整理

    目录 1. C 语言中的指针和内存...80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

    javabitset源码-JerrySoundCode:杰瑞声码

    bitset源码Java源码分析 基础集合列表 ArrayList (done) Vector (done) LinkedList (done) Stack (done) ReferenceQueue (done) ArrayDeque (done) Set HashSet (done) TreeSet (done) LinkedHashSet (done) BitSet ...

    高级C语言 C 语言编程要点

    80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450 有需要的朋友可以根据需求...

    高级进阶c语言教程..doc

    高级进阶c语言教程 ...80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

    史上最强的C语言资料

    目录 1. C 语言中的指针和内存...80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

    高级C语言详解

    目录 1. C 语言中的指针和内存...80. Hashtable和HashMap的区别 408 81. hash 表学习笔记 410 82. C程序设计常用算法源代码 412 83. C语言有头结点链表的经典实现 419 84. C语言惠通面试题 428 85. C语言常用宏定义 450

    java面试笔试资料包括JAVA基础核心知识点深度学习Spring面试题等资料合集.zip

    Spring源码分析之IoC.docx 关于线程和线程池的学习与使用.docx 深入理解JVM垃圾回收机制.docx 深入理解多线程实现的另一种方式Callable.docx 红黑树简介.docx 线程死锁及解决办法.docx 线程锁之重入锁.docx 线程间的...

    超级有影响力霸气的Java面试题大全文档

    Hashtable和HashMap采用的hash/rehash算法都大概一样,所以性能不会有很大的差异。 15、final, finally, finalize的区别。  final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 ...

Global site tag (gtag.js) - Google Analytics