HashMap 之 再哈希探究

HashTable(哈希表)是JDK 1.0时就加入的,效率低,因为线程安全

为了提高效率,JDK 1.2加入了HashMap(哈希Map),但是线程不安全。

JDK 1.5 为了解决线程安全的问题,加入了ConcurrentHashMap(并发哈希Map)。

因此一般的选择是:

  1. 单线程——HashMap
  2. 多线程——ConcurrentHashMap

特点

  1. 允许null--null 键值对
  2. 线程不安全
  3. 不保证顺序

影响HashMap性能的两个参数

  1. 初始化容量(capacity)——不要太大,默认16
  2. 负载因子(load factor)——不要太小,默认0.75

再哈希

当哈希表里的entry(键值对)超过一定阈值时,哈希表会进行再哈希(rehash)。再哈希后的哈希表的桶的个数之前的两倍 。(threshold=capacity*factor)

验证

public class HashMapL {

    public static void main(String[] args) {

        HashMap<Integer, Integer> hashMap = new HashMap<>();

        hashMap.put(null, null);  //允许空空键值对

        for(int i=0; i<16; i++){

            hashMap.put(i, i);  //自动装箱

        }

}

下面来一步步的研究

HashMap<Integer, Integer> hashMap = new HashMap<>();

从上图可以看出

负载因子——0.75

table——null。尚未分配。了解拉链式哈希表的人就会轻易知道它是一个链表数组。

阈值——0。这个值是在给table分配空间后才会计算

hashMap.put(null, null);

从上图可以看到,现在table已经初始化了。

table——拥有一个元素 "null=null",并且从图片最下面可以看到,它是一个包含16个元素的数组

table的id——24

继续按下一步,直到size=threshold=12,此刻table的id和之前的一样,还是id=24

现在再按一次下一步,向HashMap里添加一个元素,让元素的总数size大于阈值threshold

变化

id    24-->104

大小    16-->32

阈值    12-->24

结论

  1. 当size>threshold时就会进行再哈希。
  2. 再哈希后,HashMap就会自动扩容为之前的2倍,并且用一个新的对象代替原来的对象。

由此也可得知,自动扩容是需要消耗资源的,要尽量减少自动扩容的发生。

How HashMap works in java,强烈推荐!【没看】

时间: 2024-10-24 21:43:02

HashMap 之 再哈希探究的相关文章

使用再哈希算法查找元素

使用再哈希算法查找元素: /* hash search, using rehash method if find k, return if not find, d=(d+step)%m, rehash find */ int SearchHash(HashTable H, KeyType k) { int d, d1, m; m = H.tableSize; d = d1 = k%m; while(H.data[d].key != -1) { if(H.data[d].key == k) //h

HashMap/HashSet,hashCode,哈希表

HashMap实现了Map接口,该接口的作用主要是为客户提供三种方式的数据显示:只查看keys列表:只查看values列表,或以key-value形式成对查看.Map接口并没有定义数据要如何存储,也没有指定如何判定key是一样,因此并不是所有的Map实现都会与hashCode方法扯上关系,如TreeMap便是要求对象实现Comparator接口,通过其compare方法来比对两者是否一致,而非hashCode及equals.同理,如果我们自己实现Map接口,我们也可以直接使用数组进行数据存储使用

48 容器(七)——HashMap底层:哈希表结构与哈希算法

哈希表结构 哈希表是由数组+链表组成的,首先有一个数组,数组的每一个位置都用来存储一个链表,链表的基本节点为:[hash值,key值,value值,next],当存入一个键值对时,首先调用hashcode()方法获得key的hashcode,然后通过算法计算出hash值,当不同的key取到相同的hash值时,后面的key作为一个节点连接到前一个相同hash值的key的节点. hash值的算法 最差的算法:hashcode/hashcode 会将所有的元素存储在数组的下标1位,实际上已经退化为一个

Java解决Hash(散列)冲突的四种方法--开放地址法(线性探测,二次探测,伪随机探测)、链地址法、再哈希、建立公共溢出区

最近时间有点紧,暂时先放参考链接了,待有时间在总结一下: 查了好多,这几篇博客写的真心好,互有优缺点,大家一个一个看就会明白了: 参考 1. 先看这个明白拉链法(链地址法),这个带源码,很好看懂,只不过是只讲了拉链法一种: 2. 再看这个比较全的,四种全讲了,链接,这篇比较形象,有图.但是这两篇都没有仔细介绍优缺点: 3. 最后看优缺点,点击这里: 原文地址:https://www.cnblogs.com/gjmhome/p/11372883.html

java 面试题总结(一)

从网上找了些面试题,自己手工总结了理解了一下,如有理解错误,还请指正. java基础 1.String 为什么是final的? https://www.zhihu.com/question/31345592 String作为引用类型,类设计成final的,不让任何子类有机会继承它,目的时保证String可以作为一个不可变的对象存储起来. String使用非常频繁,因此设计成一种类似于int那样的值传递,需要有直接的值,而且值不能被改变,如果String的值能够被轻易改变将是非常不安全的. Str

7.哈希

哈希(Hash)又称散列,它是一个很常见的算法.在Java的HashMap数据结构中主要就利用了哈希.哈希算法包括了哈希函数和哈希表两部分.我们数组的特性可以知道,可以通过下标快速(O(1))的定位元素,同理在哈希表中我们可以通过键(哈希值)快速的定位某个值,这个哈希值的计算就是通过哈希函数(hash(key) = address )计算得出的.通过哈希值即能定位元素[address] = value,原理同数组类似. 最好的哈希函数当然是每个key值都能计算出唯一的哈希值,但往往可能存在不同的

HashMap存储原理

1.    HashMap概述 HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变. 2.    HashMap的数据结构 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外.HashMap实际上是一个"链表散列"的数据结构,即数组和链表的结合体. 3.         

【Java集合源码剖析】HashMap源码剖析

转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 HashMap简介 HashMap是基于哈希表实现的,每一个元素是一个key-value对,其内部通过单链表解决冲突问题,容量不足(超过了阀值)时,同样会自动增长. HashMap是非线程安全的,只是用于单线程环境下,多线程环境下可以采用concurrent并发包下的concurrentHashMap. HashMap 实现了Serializable接口,因此它支持序列化,

HashMap原理-1.7

之所以分两篇文章记录,因为之前一直看的1.7的源码,而且网上很多的都是关于1.7的,今天在1.8上打开源码一看,居然懵了.    没想到1.8的实现变化这么大.所有特地拿一篇文章来记录下. 本章只介绍1.7的情况 1.HashMap存储结构 哈希表是由数组+链表组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点.那么这些元素是按照什么样的规则存储到数组中呢.一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到.比如上述哈希表中,12%16=12