一、HashMap简介 1.HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。HashMap常量源码: <<运算符的意义,表示移位操作,每次向左移动一位(相对于二进制来说),表示乘以2,此处1<<4表示00001中的1向左移动了4位,变成了10000,换算成十进制就是2^4=16,也就是HashMap的默认容量就是16。加载因子(load_factor)默认为0.75,当HashMap中存储的元素的数量大于(容量×加载因子),也就是默认大于16*0.75=12时,HashMap会进行扩容的操作。 2.HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap。 3.HashMap 实现了Serializable接口,因此它支持序列化,实现了Cloneable接口,能被克隆。 4.HashMap存数据的过程: HashMap内部维护了一个存储数据的Entry数组,HashMap采用链表解决冲突,每一个Entry本质上是一个单向链表。当准备添加一个key-value对时,首先通过hash(key)方法计算hash值,然后通过indexFor(hash,length)求该key-value对的存储位置,计算方法是先用hash&0x7FFFFFFF后,再对length取模,这就保证每一个key-value对都能存入HashMap中,当计算出的位置相同时,由于存入位置是一个链表,则把这个key-value对插入链表头。 5.HashMap中key和value都允许为null。key为null的键值对永远都放在以table[0]为头结点的链表中。当key=null时,则hash值为0。 二、Hashtable简介 1.Hashtable同样是基于哈希表实现的,同样每个元素是一个key-value对,其内部也是通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长。 2.Hashtable也是JDK1.0引入的类,是线程安全的,能用于多线程环境中。 3.Hashtable同样实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆。 三、HashMap和HashTable的区别 HashMap重新计算Hash值源码://默认容量 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; //最大容量 static final int MAXIMUM_CAPACITY = 1 << 30; //默认加载因子 static final float DEFAULT_LOAD_FACTOR = 0.75f; //链表 转成 红黑树 的阈值 static final int TREEIFY_THRESHOLD = 8; //红黑树 转为 链表 的阈值 static final int UNTREEIFY_THRESHOLD = 6; //存储方式由链表转成红黑树的容量的最小阈值 static final int MIN_TREEIFY_CAPACITY = 64; //HashMap中存储的键值对的数量 transient int size; //扩容阈值,当size>=threshold时,就会扩容 int threshold; //HashMap的加载因子 final float loadFactor;
//如果原来存在相同的key-value,原来的value会被替换掉 public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
区别
HashMap
HashTable
继承的父类
AbstractMap
Dictionary
是否线程安全
否
是
是否包含contains方法
无
有(containsValue和containsKey方法)
计算hash值方式不同
重新计算key的hash值,求hash值对应的位置索引时,
index = (n – 1) & hash。将哈希表的大小固定为了2的幂,因为是取模得到索引值,故这样取模时,不需要做除法,只需要做位运算(位运算比除法的效率要高很多)计算key的hashCode(),再求hash值位置索引时计算index的方法。
int index = (hash & 0x7FFFFFFF) % tab.length;用&0x7FFFFFFF的目的是为了将负的hash值转化为正值,因为hash值有可能为负数,而&0x7FFFFFFF后,只有符号位改变,而后面的位都不变
扩容方式
哈希扩容必须要求为原容量的2倍,而且一定是2的幂次倍扩容结果,而且每次扩容时,原来数组中的元素依次重新计算存放位置,并重新插入
扩容为原容量2倍加1
解决hash冲突方式
(1)如果冲突数量小于8,则以链表方式解决冲突。
(2)而当冲突大于等于8时,就会将冲突的Entry转换为红黑树存储。
(3)而又当数量小于6时,则又转化为链表存储。以链表方式存储
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算