1. Hash

把任意长度的输入通过散列算法,变换成固定长度的输出,该输出就是散列值。拥有四个特性:

1. 拥有无限的输入域和固定大小的输出域

2. 如果输入值相同,返回值一样

3. 如果输入值不相同,返回值可能相同,可能不同

4. 不同输入值得到的哈希值,整体均匀的分布在输出域s中——优秀哈希函数的判断。

2. HashMap

HashMap是Node[] table哈希桶数组,其中Node是内部类,实现键值对Entry接口,并采用链表解决Hash碰撞问题。

数组默认初始长度为16,含有Loadfactor负载因子(默认为0.75),threshold=LoadFactor*length。当数组元素超过了threshold,则扩容成原来长度的两倍,并重新对map的内容进行hash,容量总是2的幂

所以保证Hash Map高效的因素是:好的hash算法使得hash值分布均匀和扩容机制。

在JDK8以后,加入了红黑树,当链表数量超过8时使用红黑树。

2.1 结构实现

HashMap是数组+链表实现。

1)是Entry键值对的数组 Node[] table,即哈希桶数组,其中Node是内部类,实现键值对Entry接口

2)HashMap就是使用哈希表来存储的,并且采用了链地址法解决冲突。

简单来说,就是数组加链表的结合。在每个数组元素上都一个链表结构,当数据被Hash后,得到数组下标,把数据放在对应下标元素的链表上。

  • 如果哈希桶数组很大,即使比较差的Hash算法也会比较分散
  • 如果哈希桶数组很小,即使很好的Hash算法也会出现较多的碰撞

所以,需要在时间成本和空间成本作出权衡,根据实际情况确定哈希桶数组的大小,并在此基础上设计好的hash算法减少Hash碰撞。——解决方式:Hash算法和扩容机制

2.2 扩容机制

  • Node[] table初始化长度length(默认16),一般为2的幂次方(主要是为了在取模和扩容时做优化,同时为了减少冲突,HashMap定位哈希桶索引位置时,也加入了高位参与运算的过程。)

    • vs HashTable:长度默认为11(素数,相对来说素数导致冲突的概率小于合数)
  • Load factor负载因子(默认是0.75)
  • threshold是Hash Map所能容纳的最大数据量的Node键值对。threshold = length*loadfactor
  • 当元素数量超过了threshold,那么就扩容resize,扩容后的容量是原来的两倍,并且重新计算每个元素在数组中的位置。

注意: 扩容是一个特别耗性能的操作,所以当程序员在使用HashMap的时候,估算map的大小,初始化的时候给一个大致的数值,避免map进行频繁的扩容。

2.3 功能实现

1. 确定哈希桶数组索引位置

Hash算法本质上就是三步:1)取key的HashCode值;2)高位运算;3)取模运算

方法一:把Hash值对数组取模运算。——时间消耗大

方法二:hash&(table.length-1)来得到该对象的保存位,当长度总是为2的幂次方时,相当于对length取模,但是&比%更高效。

在JDK1.8的实现中,优化了高位运算的算法,通过hashCode()的高16位异或低16位实现的:(h = k.hashCode()) ^ (h >>> 16),主要是从速度、功效、质量来考虑的,这么做可以在数组table的length比较小的时候,也能保证考虑到高低Bit都参与到Hash的计算中,同时不会有太大的开销。

2. HashMap的Put方法:

1. 首先根据键值key计算hash值,得到索引值i。

  • 如果table[i]=null,直接新建节点添加。并判断元素的数量是否超过threshold,
  • 如果table[i] !=null,则在该索引对应的链表中插入该元素

2. 判断数组中的元素数目是否超过thrshold,

  • 如果超过,则扩容resize成原来的两倍,并重新计算各元素的数组索引值。

此外:

(1) 负载因子是可以修改的,也可以大于1,但是建议不要轻易修改,除非情况非常特殊。

(2) HashMap是线程不安全的,不要在并发的环境中同时操作HashMap,建议使用ConcurrentHashMap。

(3) JDK1.8引入红黑树大程度优化了HashMap的性能。

https://zhuanlan.zhihu.com/p/21673805

3. 其他结构

1. HashMap

  • 根据键的hashcode值来存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序确实不确定的。
  • HashMap最多只允许一条记录的键为null,允许多条记录的值为null。
  • 非线程安全。即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。
  • 若要线程安全:synchronizedMap、ConcurrentHashMap

2. HashTable

是遗留类,很多映射的常用功能和Hash Map类似,不同的是它承自Dictionary类,是线程安全的。任意时刻只能有一个线程能够写HashTable,并发性不如ConcurrentHashMap,因为ConcurrentHashMap引入了分段锁。

一般不建议在新代码中使用

3. TreeMap

实现SortedMap接口,能够把它保存的记录按照键排序,默认是按键值的升序排序,也可以指定排序的比较器。在使用TreeMap时,key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常。

4. LinkedHashMap

是Hash Map的一个字类,保存了记录的插入顺序,在使用Iterator遍历LinkedhashMap时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。

HashMap VS HashTable

1. HashMap
- Entry[] table; - size>=threshold就会扩容,threshold等于capacity*loadFactor - HashMap默认的初始容量是16,负荷系数是0.75。

扩容会对map的内容进行重新哈希,容量总是2的幂。 -

数组第一个位置放得是key=null的元素 - reHash()时: int i = indexFor(e.hash, newCapacity); 然后头插法插入新数组 -自定义对象重写equals()时也要重写hashcode();使用不可变类当key;原因都是怕存入Hashmap之后get(key)找不到元素。 - jdk1.8 链表数量超过8时改用红黑树。node<k,v>[] table;node是内部类,实现Map.Entry接口{K key; V value; node<K,V> next; int hash} - jdk1.8 扩容不需要重新计算hash,因为容量扩大两倍, 那么n-1的mask范围在高位多1bit, 只需要看看原来元素的hash值新增的那个bit是1还是0,是0的元素位置没变,是1的话索引变成“原索引+旧容量(即扩大的容量)” - jdk1.8中rehash的时候,旧链表迁移新链表的时候,如果在新表的数组索引位置相同,则链表元素bu不会倒置 - jdk1.8旧链表rehash时新建两条链表AB,如果 (e.hash&oldCap)==0是指元素位置不变,尾插法插入链表A,最后B链表插入 原索引+oldCap放到bucket里 Hashtable - Entry<K,V>{final K key; V value; Entry<K,V> next;final int hash} - 计算哈希值:int hash = hash(key.hashCode()); - 计算数组落位:hash & (capacity-1),其中capacity是2的幂 - 新增加的Entry<K,V>放在链表头部 - 扩容:使用新的容量创建新数组,将每一个元素重新计算重新落位,重新计算临界值 - 查找value必须遍历整个数组遍历每个位置上的整条链表 - Hashtable不允许键或者值是null。 - Hashtable默认数组大小11,增长old*2+1,HashMap默认数组大小16,增长2的指数。 - Hashtablehash值直接使用hashCode

算法——(4)哈希、hashmap、hashtable的更多相关文章

  1. [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.

    注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhanger ...

  2. Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)

    概要 学完了Map的全部内容,我们再回头开开Map的框架图. 本章内容包括:第1部分 Map概括第2部分 HashMap和Hashtable异同第3部分 HashMap和WeakHashMap异同 转 ...

  3. 杨晓峰-Java核心技术-9 HashMap Hashtable TreeMap MD

    目录 第9讲 | 对比Hashtable.HashMap.TreeMap有什么不同? 典型回答 考点分析 知识扩展 Map 整体结构 有序 Map HashMap 源码分析 容量.负载因子和树化 精选 ...

  4. Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)

    概要 学完了Map的全部内容,我们再回头开开Map的框架图. 本章内容包括:第1部分 Map概括第2部分 HashMap和Hashtable异同第3部分 HashMap和WeakHashMap异同 转 ...

  5. hashmap hashtable

    作者:付佳豪链接:https://zhuanlan.zhihu.com/p/37607299来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 在面试的时候,java集合最 ...

  6. Map总结--HashMap/HashTable/TreeMap/WeakHashMap使用场景分析(转)

    首先看下Map的框架图 1.Map概述 1.Map是键值对映射的抽象接口 2.AbstractMap实现了Map中绝大部分的函数接口,它减少了“Map实现类”的重复编码 3.SortedMap有序的“ ...

  7. 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.

    注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享.  原文地址: http://blog.csdn.net/zhange ...

  8. HashMap Hashtable区别

    http://blog.csdn.net/java2000_net/archive/2008/06/05/2512510.aspx 我们先看2个类的定义 public class Hashtable ...

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

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

  10. 算法:哈希表格(Hash Table)

    背景 Java 和 .Net 平台都有一个所有引用类型都会间接或直接继承的类型:Object,这个类型提供最基本的相等性比较算法和哈希算法,很多书上都给出了在重写这两个算法的时候的主意事项,其中大多数 ...

随机推荐

  1. centos ssh远程登陆

    登录Centos6.5系统. ◆示例:使用root用户登录. 注:若为非root用户登录,输入执行某些命权限不够时需加sudo.   查看SSH是否安装. ◆输入命令:rpm -qa | grep s ...

  2. final关键字的特点

    1.这个关键字是一个修饰符,可以修饰类,方法,变量. 2.被final修饰的类是一个最终类,不可以被继承. 3.被final修饰的方法是一个最终方法,不可以被覆盖. 4.被final修饰的变量是一个常 ...

  3. 小工具-IP地址获取和设置及端口访问验证(windows)

    技术部在业务部门眼里就是后勤部门,业务部门要搬到新大楼去 领导要求去帮忙调试业务人员的电脑,要保证这些大爷们周一上班来,就喝着茶打开新浪,然后打开OA看看. 手上就几个桌面支持的兄弟,要弄一百台多电脑 ...

  4. UVA1185 Big Number

    题目大意:求十进制下x!的位数 这题其实就是要求\(\lg\)函数值的前缀和啊 对于一个数x,若\(\lg x=y\),则其位数为\(\lfloor y+1 \rfloor\) 然后对于对数,我们有\ ...

  5. 一类划分关系和指数级生成函数,多项式exp的关系

    划分关系 姑且这么叫着 设满足性质 \(A\) 的集合为 \(S_A\),每个元素有标号 如果 \(S_B\) 是由若干个 \(S_A\) 组成的一个大集合 设 \(a_i\) 表示大小为 \(i\) ...

  6. 理解bind函数

    前言:之前一直不懂这个函数是干嘛的,最近慢慢有点懂了,说一说自己的理解~ 本文按以下3个方面来谈谈bind函数 1)对bind函数的理解: 2)如何使用bind函数 3)自定义bind函数 (http ...

  7. 域模型中的实体类分为四种类型:VO、DTO、DO、PO

    经常会接触到VO,DO,DTO的概念,本文从领域建模中的实体划分和项目中的实际应用情况两个角度,对这几个概念进行简析. 得出的主要结论是:在项目应用中,VO对应于页面上需要显示的数据(表单),DO对应 ...

  8. maven(16)-灵活的环境构建

     多个环境 一个项目,在家的时候可能会在本机上运行,在公司可能在内网测试环境运行,上线后会在生产环境运行,在不同的环境中会有一些配置是不一样的,至少数据库就不一样.如果每换一个环境就去改所有配置太 ...

  9. PURGE 的用法说明

    PURGE PurposeUse the PURGE statement to remove a table or index from your recycle bin and release al ...

  10. Linux下调节CPU使用的几种方法

    一,使用taskset充分利用多核cpu,让cpu的使用率均衡到每个cpu上 #taskset-p,    设定一个已存在的pid,而不是重新开启一个新任务-c,    指定一个处理,可以指定多个,以 ...