HashMap的数据结构:

在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

从上图中可以看出,HashMap底层就是一个数组结构,数组中的每一项又是一个链表。当新建一个HashMap的时候,就会初始化一个数组。

1.HashMap的存取实现:

当我们往HashMap中put元素的时候,先根据key的hashCode重新计算hash值,根据hash值得到这个元素在数组中的位置(即下标),如果数组该位置上已经存放有其他元素了,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。如果数组该位置上没有元素,就直接将该元素放到此数组中的该位置上。

我们可以看到在HashMap中要找到某个元素,需要根据key的hash值来求得对应数组中的位置。如何计算这个位置就是hash算法。前面说过HashMap的数据结构是数组和链表的结合,所以我们当然希望这个HashMap里面的元素位置尽量的分布均匀些,尽量使得每个位置上的元素数量只有一个,那么当我们用hash算法求得这个位置的时候,马上就可以知道对应位置的元素就是我们要的,而不用再去遍历链表,这样就大大优化了查询的效率。

对于任意给定的对象,只要它的 hashCode()返回值相同,那么程序调用 hash(int h) 方法所计算得到的hash 码值总是相同的。我们首先想到的就是把hash值对数组长度取模运算,这样一来,元素的分布相对来说是比较均匀的。但是,“模”运算的消耗还是比较大的,在HashMap中是这样做的:调用 indexFor(int h, int length) 方法来计算该对象应该保存在 table 数组的哪个索引处。

2读取:

从HashMap中get元素时,首先计算key的hashCode,找到数组中对应位置的某一元素,然后通过key的equals方法在对应位置的链表中找到需要的元素。

归纳起来简单地说,HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry对象。HashMap 底层采用一个 Entry[] 数组来保存所有的 key-value 对,当需要存储一个 Entry 对象时,会根据hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Entry时,也会根据hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Entry。

3.    HashMap的resize(rehash):

当HashMap中的元素越来越多的时候,hash冲突的几率也就越来越高,因为数组的长度是固定的。所以为了提高查询的效率,就要对HashMap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,这是一个常用的操作,而在HashMap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。

那么HashMap什么时候进行扩容呢?当HashMap中的元素个数超过数组大小*loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,这是一个折中的取值。也就是说,默认情况下,数组大小为16,那么当HashMap中元素个数超过16*0.75=12的时候,就把数组的大小扩展为 2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。

出处:http://blog.csdn.net

java HashMap的原理的更多相关文章

  1. Java HashMap工作原理及实现

    Java HashMap工作原理及实现 2016/03/20 | 分类: 基础技术 | 0 条评论 | 标签: HASHMAP 分享到:3 原文出处: Yikun 1. 概述 从本文你可以学习到: 什 ...

  2. Java HashMap实现原理 源码剖析

    HashMap是基于哈希表的Map接口实现,提供了所有可选的映射操作,并允许使用null值和null建,不同步且不保证映射顺序.下面记录一下研究HashMap实现原理. HashMap内部存储 在Ha ...

  3. [翻译]Java HashMap工作原理

    大部分Java开发者都在使用Map,特别是HashMap.HashMap是一种简单但强大的方式去存储和获取数据.但有多少开发者知道HashMap内部如何工作呢?几天前,我阅读了java.util.Ha ...

  4. 【转】Java HashMap工作原理(好文章)

    大部分Java开发者都在使用Map,特别是HashMap.HashMap是一种简单但强大的方式去存储和获取数据.但有多少开发者知道HashMap内部如何工作呢?几天前,我阅读了java.util.Ha ...

  5. Java HashMap工作原理深入探讨

    大部分Java开发者都在使用Map,特别是HashMap.HashMap是一种简单但强大的方式去存储和获取数据.但有多少开发者知道HashMap内部如何工作呢?几天前,我阅读了java.util.Ha ...

  6. Java HashMap工作原理及实现[转]

    原文:http://yikun.github.io/2015/04/01/Java-HashMap%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E5%8F%8A%E5%AE ...

  7. 160706、Java HashMap工作原理及实现

    1. 概述 从本文你可以学习到: 什么时候会使用HashMap?他有什么特点? 你知道HashMap的工作原理吗? 你知道get和put的原理吗?equals()和hashCode()的都有什么作用? ...

  8. Java HashMap实现原理分析

    参考链接:https://www.cnblogs.com/xiarongjin/p/8310011.html 1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是 ...

  9. Java HashMap工作原理:不仅仅是HashMap

    前言: 几乎所有java程序员都用过hashMap,但会用不一定会说. 近年来hashMap是非常常见的面试题,如何为自己的回答加分?需要从理解开始. "你用过hashMap吗?" ...

随机推荐

  1. jquery的.detach()方法

    .detach()就是从DOM中删除所有匹配的元素. 与.remove()方法不同的是, 这个方法不会把匹配的元素从jQuery对象中删除,所有绑定的事件.附加的数据等都会保留下来,因而可以在将来再使 ...

  2. web标准(复习)--4 纵向导航菜单及二级弹出菜单

    今天我们开始学习纵向导航菜单及二级弹出菜单,包含以下内容和知识点: 纵向列表 标签的默认样式 css派生选择器 css选择器的分组 纵向二级列表 相对定位和绝对定位 一.纵向列表纵向列表或称为纵向导航 ...

  3. 类和对象:一些相关的BIF - 零基础入门学习Python040

    类和对象:一些相关的BIF 让编程改变世界 Change the world by program 一些类和对象相关的 BIF 今天我们来谈谈跟类和对象相关的一些BIF(内置函数): issubcla ...

  4. Python学习笔记整理(十七)异常处理

    一.异常基础 try/except:捕捉由代码中的异常并恢复,匹配except里面的错误,并自行except中定义的代码,后继续执行程序(发生异常后,由except捕捉到异常后,不会中断程序,继续执行 ...

  5. CSAPP--优化程序性能

    一.编写高效的程序: 1.选择合适的算法和数据结构. 2.编写出编译器能够有效优化以转换为高效可执行的源代码. 3.并行计算.当然重点还是第一个,良好的算法和数据结构大大减小了程序的时间复杂度. 二. ...

  6. WPF异常“调用线程无法访问此对象,因为另一个线程拥有该对象 ”

    WPF中在对界面进行操作的时候,可能会遇到"调用线程无法访问此对象,因为另一个线程拥有该对象"异常,这是因为WPF中只有UI线程才能操作UI元素,非UI线程要访问UI时就会报异常了 ...

  7. C 和 C++的 不同

    转自: http://studytipsandtricks.blogspot.com/2012/05/15-most-important-differences-between-c.html Basi ...

  8. 宏汇编软件MASM51的使用

    单片机开发可以用手工汇编和机器汇编两种方法.采用手工汇编就是先编写出汇编程序,然后对照单片机汇编表手工将汇编程序翻译成机器码,最后将机器码一个一个地送入开发仿真器的RAM中去进行调试. 由于采用手工汇 ...

  9. leetcode: sortlist之四种方法

    原题链接:https://oj.leetcode.com/problems/sort-list/ 题目:空间复杂度为常数,时间复杂度为O(nlogn)的排序链表实现 方法一:第一想法是模拟数组的快速排 ...

  10. back_inserter的用法

    1,代码如下: #include<iostream> #include<list> #include<algorithm> #include<iterator ...