博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HashMap
阅读量:5090 次
发布时间:2019-06-13

本文共 2683 字,大约阅读时间需要 8 分钟。

目录

参考:

数据结构

jdk1.8:数组、链表/红黑树(jdk1.7的是数组+链表)

1400844-20190208151237091-1174963636.png

节点数据类型:

Node<K,V>(hash,key,value,next)

static class Node
implements Map.Entry
{ // key & value 的 hash值 final int hash; final K key; V value; //指向下一个节点 Node
next; Node(int hash, K key, V value, Node
next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } public final K getKey() { return key; } public final V getValue() { return value; } public final String toString() { return key + "=" + value; } public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); } public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } public final boolean equals(Object o) { if (o == this) return true; if (o instanceof Map.Entry) { Map.Entry
e = (Map.Entry
)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) return true; } return false; }}

参数

/默认初始化map的容量:16static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;//map的最大容量:2^30static final int MAXIMUM_CAPACITY = 1 << 30;//默认的填充因子:0.75,能较好的平衡时间与空间的消耗static final float DEFAULT_LOAD_FACTOR = 0.75f;//将链表(桶)转化成红黑树的临界值static final int TREEIFY_THRESHOLD = 8;//将红黑树转成链表(桶)的临界值static final int UNTREEIFY_THRESHOLD = 6;//转变成树的table的最小容量,小于该值则不会进行树化static final int MIN_TREEIFY_CAPACITY = 64;//上图所示的数组,长度总是2的幂次transient Node
[] table;//map中的键值对集合transient Set
> entrySet;//map中键值对的数量transient int size;//用于统计map修改次数的计数器,用于fail-fast抛出ConcurrentModificationExceptiontransient int modCount;//大于该阈值,则重新进行扩容,threshold = capacity(table.length) * load factorint threshold;//填充因子final float loadFactor;

重要方法

get

根据key的hashCode计算在数组里的下标,然后再判断该位置是否符合条件,否则根据链表/红黑树的方法继续找

计算下标的方法:

下标 = (n-1) & hash
hash = (h = key.hashCode()) & h>>>16

判断两个key是否相同:

if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))

先判断hash,如果hash不同一定不同;如果hash相同,则利用equals判断是否相同

put

先检查容量(扩容resize)。

根据hashCode计算桶在数组里的位置,
插入该处的链表/树

resize

两倍容量。如果容量已达最大值,则设置容量为int_max。

扩容之后要重新计算index,每个桶里的节点都要重新计算位置,计算位置的方法是hash & (n-1)。
扩容之后由于newCap-1比oldCap-1多了一个高位(例如8-1=7=111,而4-1=3=11),因此节点的新位置取决于多出来的一个高位bit,如果该位是0,则还是原位置;否则应该是原位置+旧容量

扩容的过程对整个数组和桶进行了遍历,耗费性能,所以最好在创建HashMap的时候指定容量,否则在第一次put的时候会进行一次扩容(因为table==null)

HashMap与HashTable的区别

  • 线程安全性:Hash Table线程安全,HashMap线程不安全
  • null键值的支持:HashMap最多有一个null键,null值不做约束;HashTable不接受null键值
  • 初始容量及扩容:HashTable初始容量11,扩容2n+1;HashMap初始容量16,扩容2n(即容量时钟2的幂)
  • 数据结构:jdk8以后HashMap加入了红黑树提高链表过长时的查询速度,HashTable没有

参考:

转载于:https://www.cnblogs.com/darknessplus/p/10356235.html

你可能感兴趣的文章
unison+inotify数据实时双向同步
查看>>
php对mysql的相关操作
查看>>
基元线程同步构造
查看>>
ElasticSearch 获取es信息以及索引操作
查看>>
Apollo快速安装视频教程
查看>>
mysql 用户管理和权限设置(转)
查看>>
PHP进程通信基础——信号
查看>>
32复用
查看>>
COGS 1578. 次小生成树初级练习题
查看>>
工作三年的思考
查看>>
jquery $.fn $.fx是什么意思有什么用
查看>>
javaWeb中的文件上传下载
查看>>
开始学习MFC
查看>>
第三周作业(三)
查看>>
手把手教你如何使用webpack+react
查看>>
Java设计模式-----单例模式
查看>>
组合和继承
查看>>
Mondrian系列
查看>>
推荐移动应用:群落(Groupcells)——全球第一款基于图片组的近场社交电子商务平台...
查看>>
WEB安全 php+mysql5注入防御(一)
查看>>