聊聊传说中的散列哈希Hash算法,以及Java中的HashTable,HashMap,HashSet,ConcurrentHashMap......
建议本文结合java源码来阅读,看了之后就什么都懂了,还有参考文献。
- 散列(Hash) 是一种按关键字编址的存储和检索方法
- 散列表(HashTable)根据元素的关键字确定元素的位置
- 散列函数(Hash Function)建立数据元素的关键字到该元素的存储位置的一种映射关系
(具体如何计算百度一下很简单,Hash算法的难处在如何确定散列函数和解决冲突)
常见的散列函数计算方法
- 除留余数法
int hash(int key)
{return key%prime;
}
如果key的类型是T 要返回一个 int hashCode() 返回散列码,约定对象到int的一对一映射,每个对象的散列码必须不同
template<T>
int HashSet<T>::set(T key)
{return key.hashCode() %prime;
}
除留余数法的关键在于如何选取prime的值。通常选取小于散列表长度的最大素数。
- 平方取中法 例如,k=4731,k2=22382361,若表长为100,取中间两位。hash(k)=82
- 全域散列法:在所有的散列函数中随机的选取一个散列函数,以防止n个关键字全部散列到同一个槽中
处理冲突
- 链地址法。将同义词冲突的元素存储在一条同义词单链表中。
下面来谈一下java中的hash集合
HashMap
取hashMap的方法
System.out.println("里面的键值对是:");
Set<Map.Entry<String, String>> set = map.entrySet();
Iterator<Map.Entry<String, String>> iterator2 = set.iterator();
while (iterator2.hasNext()) { Map.Entry<String, String> entry = iterator2.next(); System.out.println("键是:" + entry.getKey() + "值是:" + entry.getValue());
}
谈谈你理解的 HashMap,讲讲其中的 get put 过程。
- 是由数组加链表组成,
- put过程会根据key的hashcode做hash,如果没碰撞直接放到桶里,如果碰撞了,则执行equals()函数判断key是否相等,如果相等进行覆盖,不相等,以链表的形式存放,如果长度于TREEIFY_THRESHOLD,就把链表转换成红黑树,桶满了要resize() 超过了load factor * current capacity
- get 如果桶中只有一个节点则命中,如果有冲突则通过key.equals去查找要查找的值,有红黑树和链表两种。
1.8 做了什么优化?
- 在1.8之前是用链表解决冲突的,1.8采用的红黑树解决冲突时间复杂度编程logn
你知道hash的实现吗?为什么要这样实现?
- 在Java 1.8的实现中,是通过hashCode()的高16位异或低16位实现的:(h = k.hashCode()) ^ (h >>> 16),主要是从速度、功效、质量来考虑的,这么做可以在bucket的n比较小的时候,也能保证考虑到高低bit都参与到hash的计算中,同时不会有太大的开销。
是线程安全的嘛?
- 不是线程安全的,线程安全的有HashTable和ConcurrentHashMap.
不安全会导致哪些问题?
- 原子性,有序性,可见性
ConcurrentHashMap 是如何实现的? 1.7、1.8 实现有何不同?为什么这么做?
原理上来说:ConcurrentHashMap 采用了分段锁技术。不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理,理论上 ConcurrentHashMap 支持 CurrencyLevel 的线程并发。jdk 1.7使用segment存放数据,segment继承了ReentrantLock充当锁的角色,为每一个segment提供了线程安全的保障,segment维护了哈希的若干个桶,每个桶由HashEntry构成链表。1.8舍弃了segment,大量使用了synchronized,以及CAS无锁操作以保证ConcurrentHashMap操作的线程安全性。至于为什么不用 ReentrantLock 而是 Synchronzied 呢?实际上,synchronzied 做了很多的优化,包括偏向锁,轻量级锁,重量级锁,可以依次向上升级锁状态,但不能降级,因此,使用 synchronized 相较于 ReentrantLock 的性能会持平甚至在某些情况更优。另外,底层数据结构改变为采用数组+链表+红黑树的数据形式。
HashTable和HashMap的区别
- HashMap不是线程安全的,但是效率较高,HashTable是线程安全的但是效率较低,因为put和get的操作都加上了同步锁,解决这个问题就是用ConcurrentHashMap
HashTable和ConcurrentHashMap的区别
- HashTable的put和get操作都用到了同步锁是一种悲观锁效率比较低。
- ConcurrentHashMap用的是同步锁加CAS无锁操作,通过加transient关键字来实现。
- put操作。
- 如果没有初始化就先调用initTable()方法来进行初始化过程
- 如果没有hash冲突就直接CAS插入
- 如果还在进行扩容操作就先进行扩容如果存在hash冲突,就加锁来保证线程安全,这里有两种情况,一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入,最后一个如果该链表的数量大于阈值8,就要先转换成黑红树的结构,break再一次进入循环如果添加成功就调用addCount()方法统计size,并且检查是否需要扩容
- get操作
- 计算hash值,定位到该table索引位置,如果是首节点符合就返回
- 如果遇到扩容的时候,会调用标志正在扩容节点ForwardingNode的find方 法,查找该节点,匹配就返回
- 以上都不符合的话,就往下遍历节点,匹配就返回,否则最后就返回null
HashSet
- HashSet是基于HashMap来实现的,操作很简单,更像是对HashMap做了一次“封装”,而且只使用了HashMap的key来实现各种特性。
LinkedHashMap和LinkedHashSet
- LinkedHashSet就是继承了HashSet维护一个双链表和LinkedHashMap一样。、
- LinkedHashMap 是 HashMap 的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用 LinkedHashMap。
参考文献
1.java源码
2.《数据结构(C++版)》 叶核亚编著
3.ConcurrentHashMap
4.Java并发编程:volatile关键字解析
5.java HashMap工作原理及实现
6.java中Cloneable和Serializable接口详情
7.Java transient关键字使用小记
8.无锁算法——CAS原理
9.HashTable,ConcurrentHashMap
10.LinkedHashMap
聊聊传说中的散列哈希Hash算法,以及Java中的HashTable,HashMap,HashSet,ConcurrentHashMap......相关推荐
- 散列(哈希 hash)
目录 前言 hash介绍 字符串hash初步 练习题 前言 散列(hash)是常用的算法之一. 为了了解hash我们先看一个简单的题. 题目: 给出N个正整数,再给出M个正整数,问这M个数中的每个数分 ...
- Java 国密算法 SM3 散列哈希使用
Java 国密算法 SM3 散列哈希使用 文章目录 Java 国密算法 SM3 散列哈希使用 引入依赖 计算散列哈希 引入依赖 <dependency><groupId>org ...
- 对一致性Hash算法,Java代码实现的深入研究
一致性Hash算法 关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法.一致性 ...
- 一致性Hash算法(JAVA版)(摘抄至五月的仓颉的博客)
一致性Hash算法 关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法.一致性 ...
- 生成FaceBook所需的散列哈希值
Hex to base64 converter FaceBook后台发布应用时,需要填入hash值,今天自己用openssl生成的时候只有24位并不正确,与其费劲巴拉的自己折腾openssl,还是感谢 ...
- 常见的哈希Hash算法 MD5 对称非对称加密 海明码
2019独角兽企业重金招聘Python工程师标准>>> 参考 Link 另外,这篇文章也提到了利用Hash碰撞而产生DOS攻击的案例: http://www.cnblogs.com/ ...
- 【IoT】加密与安全:哈希 Hash 算法用途与原理解析
1.Hash 算法分类 MD5 和 SHA-1 是目前应用最广泛的 Hash 算法且是以 MD4 算法为基础设计的. 1) MD4 MD4(RFC 1320) 是 MIT 的 Ronald L. Ri ...
- hash的算法 java_【数据结构与算法】一致性Hash算法及Java实践
追求极致才能突破极限 一.案例背景 1.1 系统简介 首先看一下系统架构,方便解释: 页面给用户展示的功能就是,可以查看任何一台机器的某些属性(以下简称系统信息). 消息流程是,页面发起请求查看指定机 ...
- 一致性Hash算法及Java实践
目录 一.案例背景 1.1 系统简介 1.2 遇到问题 1.3 初步优化 1.4 继续优化 二.使用一致性Hash解决问题 三.一致性Hash介绍 3.1 理论简介 3.2 设计实现 四.对一致性Ha ...
最新文章
- 智能写作全景介绍:从最新前沿技术到行业落地解析
- CDC,CPaintDC,CClientDC,CWindowDC区别
- 浏览器兼容性导致网址显示不完整
- mysql数据库子查询的使用_MySQL数据库使用子查询方式更新数据优化及思考
- python各种类型转换-int,str,char,float,ord,hex,oct等
- DevOps vs. Agile:它们有什么共同点?
- php mysql设计中验证码的实现_php如何实现验证码功能
- ThinkPHP admin.php后台登录
- WEB应用中的信息泄漏以及攻击方法
- CCF201503-5 最小花费(100分解题链接)
- Winform 中 dataGridView 导出到Excel中的方法总结
- C#DataGridView中的常用技巧
- linux exec操作文件描述符
- “酸碱体质理论”是个骗局
- 小米安装linux驱动怎么安装教程,小米手机驱动程序怎么安装教程【图文版】
- win32com在wps上另存为SaveAs报错
- java 百度经纬度 转换为 高德经纬度 谷歌
- matlab中的矩阵求和
- 阿里玄难:面向不确定性的软件设计几点思考
- 网络精英赛模拟练习(4)