转自:http://www.cnblogs.com/carbs/archive/2012/07/04/2576995.html

Hashtable 和 HashMap 做为 Map 的基本特性
两者都实现了Map接口,基本特性相同
-          对同一个Key,只会有一个对应的value值存在
-          如何算是同一个Key? 首先,两个key对象的hash值相同,其次,key对象的equals方法返回真
内部数据结构
Hashtable和HashMap的内部数据结构相似

 
其基本内部数据结构是一个Entry数组 (transient Entry[] table)
-          数组元素为实现Map.Entry<K,V>接口的类,Hashtable和HashMap各自实现了自己的Entry类。
-          Entry包含一个Key-value对,以及一个next指针指向另一个Entry。多个Entry可以组成一个单向链表。
常用操作
数据插入操作: put(key,value)
-          根据Key的hash值计算出该Entry所应存放的位置(数组下标)
-          若该数组元素为空,直接放置Entry到此处
-          若多个不同的Key所计算得到的数组下标相同,新加入的Key-value对(Entry)会被加入到Entry单向链表中。Hashtable和HashMap都是将其插入链表首部.
-          若已经有相同的Key存在于这个链表中,则,新的value值会取代老的value
-          当Map中存放的Entry数量超过其限制( 数组长度 * 负荷因子)时,Map将自动重新调整数组大小并重新对Entry进行散列
 
 
数据查找:get(key)
-          根据Key的hash值计算出该Entry对所应存放的位置(数组下标)
-          得到该位置的第一个Entry对象,比较key和Entry.key,若hash值相同,并且equals为真,则该Entry是我们要找的Key-value对,否则继续沿next指针构成的单向链表查找
 
数据移除:remove(key)
-          按照上述数据查找的方式找到key所在的Entry对象,将其移除,并保持Entry单向链表的连通性
Hashtable 和 HashMap 的比较
 
Hashtable
HashMap
并发操作
使用同步机制,
实际应用程序中,仅仅是Hashtable本身的同步并不能保证程序在并发操作下的正确性,需要高层次的并发保护。
下面的代码试图在key所对应的value值等于x的情况下修改value为x+1
{
 value = hashTable.get(key);
   if(value.intValue()== x){
hashTable.put(key,      new Integer(value.intValue()+1));
   }
}
如2个线程同时执行以上代码,可能放入不是x+1,而是x+2.
没有同步机制,需要使用者自己进行并发访问控制
数据遍历的方式
Iterator 和 Enumeration
Iterator
是否支持fast-fail
用Iterator遍历,支持fast-fail
用Enumeration不支持fast-fail.
支持fast-fail
是否接受值为null的Key 或Value?
不接受
接受
根据hash值计算数组下标的算法
当数组长度较小,并且Key的hash值低位数值分散不均匀时,不同的hash值计算得到相同下标值的几率较高
 
hash = key.hashCode();
index=(hash&0x7FFFFFFF) % tab.length;
优于hashtable,通过对Key的hash做移位运算和位的与运算,使其能更广泛地分散到数组的不同位置
 
hash = hash (k);
index = indexFor(hash, table.length);
 
static int hash(Object x) {
 int h = x.hashCode();
h += ~(h << 9);
 h ^= (h >>> 14);
  h += (h << 4);
 h ^= (h >>> 10);
 return h;
}
static int indexFor(int h, int length) {
return h & (length-1);
}
 
Entry数组的长度
Ø         缺省初始长度为11,
Ø         初始化时可以指定initial capacity
Ø         缺省初始长度为16,
Ø         长度始终保持2的n次方
Ø         初始化时可以指定initial capacity,若不是2的次方,HashMap将选取第一个大于initial capacity 的2n次方值作为其初始长度
LoadFactor负荷因子
0.75
负荷超过(loadFactor * 数组长度)时,内部数据的调整方式
扩展数组:2*原数组长度+1
扩展数组: 原数组长度 * 2
两者都会重新根据Key的hash值计算其在数组中的新位置,重新放置。算法相似,时间、空间效率相同
 
一般情况下,HashMap能够比Hashtable工作的更好、更快,主要得益于它的散列算法,以及没有同步。应用程序一般在更高的层面上实 现了保护机制,而不是依赖于这些底层数据结构的同步,因此,HashMap能够在大多应用中满足需要。推荐使用HashMap,如果需要同步,可以使用同 步工具类将其转换成支持同步的HashMap。
Map的效率
Map的效率与Entry数组大小及负荷因子的选取有密切关系。选取适当的数组大小有利于Key-value对的散列分布,并且,如果数组足够 大,将有效的减少重新调整数组的次数,提高效率。较小的负荷因子将占用更多的空间,但降低冲突的可能性,从而将加快访问和更新的速度。
另外,Key的hash值本身如果能保证较好的散列性,也有益于提高Map的读写效率。在effective java中,对hash()的重载有好的建议。
关于如何提高Map的执行效率,可参考《Java Map 集合类简介》http://www.oracle.com/technology/global/cn/pub/articles/maps1.html
 
辨析
 “Hashtable和HashMap的区别主要是前者是同步的,后者是快速失败机制保证不会出现多线程并发错误(Fast-Fail)。”,这是一个被很多文章转载过的概念,但其描述并不准确,容易引起误会。
实质上,Fast-fail与同步保护的是两种不同情况下的并发,两者不能拿来做比较。
Hashtable是同步的,在执行get,put,remove,size,clear等一次性读写操作时,使用了同步机制,避免了多个线程 同时读写Hashtable。但同步机制并不能避免在iterator或Enumeration遍历过程中其他线程对Hashtable的put、 remove、clear操作,这些写操作都会被毫无阻拦得成功执行。
快速失败机制主要目的在于使iterator遍历数组的线程能及时发现其他线程对Map的修改(如put、remove、clear等),因 此,fast-fail并不能保证所有情况下的多线程并发错误,只能保护iterator遍历过程中的iterator.next()与写并发.
其次,Hashtable的iterator遍历方式也是支持fast-fail的,不能说它没有快速失败机制。写一个简单的例程就可以证明这 一点,一个线程做iterator遍历,另一个线程向hashtable中put新的key和value,很容易就会观察到fast-fail 机制报告 ConcurrentModificationException

(转)hashmap hashtable 的区别 Hash table 内部的数据结构的更多相关文章

  1. HashMap & HashTable的区别

    HashMap & HashTable的区别主要有以下: 1.HashMap是线程不安全的,HashTable是线程安全的.由这点区别可以知道,不考虑线程安全的情况下使用HashMap的效率明 ...

  2. [转载]hashmap hashtable 的区别

    Hashtable 和 HashMap 做为 Map 的基本特性 两者都实现了Map接口,基本特性相同 -          对同一个Key,只会有一个对应的value值存在 -          如 ...

  3. [置顶] HashMap HashTable HashSet区别剖析

    HashMap.HashSet.HashTable之间的区别是Java程序员的一个常见面试题目,在此仅以此博客记录,并深入源代码进行分析: 在分析之前,先将其区别列于下面 1:HashSet底层采用的 ...

  4. HashMap HashTable HashSet区别剖析

    HashMap.HashSet.HashTable之间的区别是Java程序员的一个常见面试题目,在此仅以此博客记录,并深入源代码进行分析: 在分析之前,先将其区别列于下面 1:HashSet底层采用的 ...

  5. 六.HashMap HashTable HashSet区别剖析总结

    HashMap.HashSet.HashTable之间的区别是Java程序员的一个常见面试题目,在此仅以此博客记录,并深入源代码进行分析: 在分析之前,先将其区别列于下面: 1.HashSet底层采用 ...

  6. HashMap,HashTable,TreeMap区别和用法

    开始学HashTable,HashMap和TreeMap的时候比较晕,觉得作用差不多,但是到实际运用的时候又发现有许多差别的.需要大家注意,在实际开发中以需求而定. java为数据结构中的映射定义了一 ...

  7. ConcurrentHashMap以及HashMap,HashTable的区别

    ConcurrentHashMap与HashMap,和HashTable 的区别? ConcurrentHashMap是一个线程安全的key-value数据结构,而HashMap不是.Concurre ...

  8. 几种常见 容器 比较和分析 hashmap, map, vector, list ...hash table

    list支持快速的插入和删除,但是查找费时; vector支持快速的查找,但是插入费时. map查找的时间复杂度是对数的,这几乎是最快的,hash也是对数的.  如果我自己写,我也会用二叉检索树,它在 ...

  9. Java集合——HashMap,HashTable,ConcurrentHashMap区别

    Map:“键值”对映射的抽象接口.该映射不包括重复的键,一个键对应一个值. SortedMap:有序的键值对接口,继承Map接口. NavigableMap:继承SortedMap,具有了针对给定搜索 ...

随机推荐

  1. 学习R语言的一点小心得

    1.目前R 语言处于入门阶段吧,能够执行一些简单的模型了,还是有收获的. 但是在跑模型的时候经常遇到各种各样的错误,最常见的错误就是数据带入模型之后,数据的类型不对,因此模型跑不下去,因此说,利用he ...

  2. Chapter2二分与前缀和

    Chapter 2 二分与前缀和 +++ 二分 套路 如果更新方式写的是R = mid, 则不用做任何处理,如果更新方式写的是L = mid,则需要在计算mid是加上1. 1.数的范围 789 #in ...

  3. SOA分析浅谈

    根据百度定义:面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和契约联系起来.接口是采用中立的方式进行定义的,它应该独立于实现服 ...

  4. web端常见测试

    一.登录注册功能 1.页面调转 2.tab键与enter键 3.密码加密显示,是否支持复制粘贴 4.账号密码校验 5.刷新页面,更新验证码 二.界面测试 1.样式.颜色.整体布局风格 2.最大化.最小 ...

  5. exiftool生成XMP文件方法

    ExifTool是一个独立于平台的Perl库,另外还有一个命令行应用程序,用于读取,编写和编辑各种文件中的元信息.ExifTool支持许多不同的元数据格式,包括EXIF,Gps,IPTC,XMP,JF ...

  6. springboot的yml配置文件里有多个参数的调用方式

    本篇教程适用于配置文件一级下有多个二级或三级时,如何在service层不用通过多个@Value就能获取配置文件的参数 例如yml配置是这样的: 如果service层要引用这些参数,用多个@Value( ...

  7. ArcGISServer发布流程

    发布数据服务 在进行WebGIS开发中,地图显示的内容可以分成两类:一类是底图,或者是矢量的世界地图.中国地图.某个地区的底图:另一类就是业务图,对于用于遥感数据发布的WebGIS应用就是遥感影像的边 ...

  8. vue中的this.$nextTick()使用

    首先我们来翻译一下nextTick是什么意思:下一个刻度 再来看看vue官网怎么说的: Vue.nextTick( [callback, context] )在下次 DOM 更新循环结束之后执行延迟回 ...

  9. C# LINQ学习笔记二:LINQ标准查询操作概述

    本笔记摘抄自:https://www.cnblogs.com/liqingwen/p/5801249.html,记录一下学习过程以备后续查用. “标准查询运算符”是组成语言集成查询 (LINQ) 模式 ...

  10. app遮罩层--网赚

    css .mask{display: none; position: fixed; width: 100%; height: 100%; top:0; background: rgba(0, 0, 0 ...