关闭

HashMap的基本原理

标签: Java
31人阅读 评论(0) 收藏 举报
分类:

HashMap的实现原理

概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

数据结构:HashMap是一个“链表散列”的数据结构,即数组和链表的结合体 hashmap 其实就是一个数组 数组的每个位置放的一个Entry即key-value键值对

当使用put方法时:


public V put(K key, V value) {  
    // HashMap允许存放null键和null值。  
    // 当key为null时,调用putForNullKey方法,将value放置在数组第一个位置。  
    if (key == null)  
        return putForNullKey(value);  
    // 根据key的keyCode重新计算hash值。  
    int hash = hash(key.hashCode());  
    // 搜索指定hash值在对应table中的索引。  
    int i = indexFor(hash, table.length);  
    // 如果 i 索引处的 Entry 不为 null,通过循环不断遍历 e 元素的下一个元素。  
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {  
        Object k;
        //找到指定的key与需要放入的key相比(hash值相同//通过equals比较返回true)
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {  
            V oldValue = e.value;  
            e.value = value;  
            e.recordAccess(this);  
            return oldValue;  
        }  
    }  
    // 如果i索引处的Entry为null,表明此处还没有Entry。  
    modCount++;  
    // 将key、value添加到i索引处。  
    addEntry(hash, key, value, i);  
    return null;  
} 

上面的代码提供了一个根据hashCode()返回值来计算hash码的方法 hash() 这个方法是一个纯粹的数学计算

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

对于任意给定的对象,只要他的hashCode()值相同,那么程序调用hash(int h)方法所计算得到的hash码值总是相同的接下来程序会调用indexFor(),来计算该对象应该保存在table数组的哪个索引处:

static int indexFor(int h, int length) {  
    return h & (length-1);  
}  

当程序试图将一个key-value对放入HashMap中时,程序首先根据该 key 的 hashCode() 返回值决定该 Entry 的存储位置:如果两个 Entry 的 key 的 hashCode() 返回值相同,那它们的存储位置相同。如果这两个 Entry 的 key 通过 equals 比较返回 true,新添加 Entry 的 value 将覆盖集合中原有 Entry 的 value,但key不会覆盖。如果这两个 Entry 的 key 通过 equals 比较返回 false,新添加的 Entry 将与集合中原有 Entry 形成 Entry 链,而且新添加的 Entry 位于 Entry 链的头部

当使用get()方法时:

public V get(Object key) {  
    if (key == null)  
        return getForNullKey();  
    int hash = hash(key.hashCode());  
    for (Entry<K,V> e = table[indexFor(hash, table.length)];  
        e != null;  
        e = e.next) {  
        Object k;  
        if (e.hash == hash && ((k = e.key) == key || key.equals(k)))  
            return e.value;  
    }  
    return null;  
} 

当取值的时候,还是先根据keycode算出在数组的储存位置,然后根据equals取出在Entry链的位置

哈希冲突

当HashMap中的元素越来越多的时候,hash冲突的几率也就越来越高,因为数组的长度是固定的。所以为了提高查询的效率,就要对HashMap的数组进行扩容,数组扩容这个操作也会出现在ArrayList中,这是一个常用的操作,而在HashMap数组扩容之后,最消耗性能的点就出现了:原数组中的数据必须重新计算其在新数组中的位置,并放进去,这就是resize。 那么HashMap什么时候进行扩容呢?当HashMap中的元素个数超过数组大小*loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,这是一个折中的取值。也就是说,默认情况下,数组大小为16,那么当HashMap中元素个数超过16*0.75=12的时候,就把数组的大小扩展为 2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知HashMap中元素的个数,那么预设元素的个数能够有效的提高HashMap的性能。

hashmap的性能参数

HashMap的性能参数:

HashMap 包含如下几个构造器:

HashMap():构建一个初始容量为 16,负载因子为 0.75 的 HashMap。

HashMap(int initialCapacity):构建一个初始容量为 initialCapacity,负载因子为 0.75 ### 的HashMap。loadFactor):以指定初始容量、指定的负载因子创建一个 ### HashMap。

HashMap的基础构造器HashMap(int initialCapacity, float ### loadFactor)带有两个参数,它们是初始容量initialCapacity和加载因子loadFactor。 ### initialCapacity:HashMap的最大容量,即为底层数组的长度。

loadFactor:负载因子loadFactor定义为:散列表的实际元素数目(n)/ 散列表的容量(m)。 ### 负载因子衡量的是一个散列表的空间的使用程度,负载因子越大表示散列表的装填程度越高,反之### 愈小。对于使用链表法的散列表来说,查找一个元素的平均时间是O(1+a),因此如果负载因子越大### ,对空间的利用更充分,然而后果是查找效率的降低;如果负载因子太小,那么散列表的数据将过### 于稀疏,对空间造成严重浪费。

1
0
查看评论

HashMap基本原理

当HashMap被初始化时,会创建一个Entry数组。数组里每个存储单元可以存放一个Entry, 在Entry对象中包括Key, Value, hash,还有对下一个Entry对象的引用,这样就可以形成一个Entry链。把这个Entry链的所有元素可以抽象看作是放在一个bucket(桶)里面的,一个...
  • Butcher__
  • Butcher__
  • 2017-02-23 22:02
  • 102

Java HashMap笔记之一:基本原理

摘要: Java中的HashMap是一种简单易用而且高效强大的数据结构,在开发过程中经常使用。这里总结下HashMap的基本原理。HashMap默认内部数组大小?HashMap内部数组为16(JDK7和JDK8都是)。HashMap Default Capacity如果初始 ... ...
  • x380481791
  • x380481791
  • 2017-07-29 09:24
  • 121

HashMap的基本原理与它的线程安全性

http://blog.csdn.net/t894690230/article/details/51323946 1. 前言 能用图说清楚的,就坚决不用代码。能用代码撸清楚的,就坚决不写解释(不是不写注释哦)。 以下所有仅针对JDK 1.7及之前中的HashMap。 ...
  • z69183787
  • z69183787
  • 2017-04-11 15:45
  • 612

垃圾回收器的基本原理

GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。垃圾回收的优点和...
  • Amen_Wu
  • Amen_Wu
  • 2017-01-09 23:25
  • 1367

【SSH】——Struts由来以及基本原理

Struts,最初的意思是:框架的,支杆。用来支持JSP,Servlet等技术在Web项目中的应用。它的目的是帮助我们减少在运用MVC设计模型来开发Web应用的时间。          在使用Struts之前...
  • u013035538
  • u013035538
  • 2016-07-06 22:44
  • 450

MapReduce的基本原理

MapReduce是一个软件框架,可方便的编写应用程序,以并行的方式在数千商用硬件组成的集群节点中处理数TB的数据,并且提供了可靠性和容错的能力。 MapReduce处理模型包括两个独立的步骤: 1.并行Map阶段,输入数据被分割成离散块以便可以单独处理; 1.5shuffle阶段,每个R...
  • u013063153
  • u013063153
  • 2016-11-10 15:50
  • 640

软件工程的七条基本原理是?

1、用分阶段的生命周期计划严格管理 2、坚持进行阶段评审 3、实行严格的产品控制 4、采用现代程度设计技术 5、结果应能清楚地审查 6、开发小组的人员应该少而精 7、承认不断改进软件实践的必要性
  • cdh1213
  • cdh1213
  • 2014-03-11 10:38
  • 513

HashMap的工作原理--重点----数据结构示意图的理解

HashMap的工作原理是近年来常见的Java面试题。几乎每个Java程序员都知道HashMap,都知道哪里要用HashMap,知道HashTable和HashMap之间的区别,那么为何这道面试题如此特殊呢?是因为这道题考察的深度很深。这题经常出现在高级或中高级面试中。投资银行更喜欢问这个问题,甚至...
  • qq_27093465
  • qq_27093465
  • 2016-08-15 11:43
  • 4021

Dijkstra算法原理

原文地址: http://www.cnblogs.com/skywang12345/p/3711516.html Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展...
  • yalishadaa
  • yalishadaa
  • 2017-02-19 22:46
  • 756

HashMap 主要特点和关键方法源码解读

点击查看 Java 集合框架深入理解 系列 什么是 HashMapHashMap 的特点HashMap 的 13 个成员变量HashMap 的初始容量和加载因子HashMap 的关键方法 HashMap 的 4 个构造方法HashMap 中的链表节点HashMap 中的添加操作Has...
  • cslbupt
  • cslbupt
  • 2017-03-28 09:57
  • 1475
    个人资料
    • 访问:354次
    • 积分:67
    • 等级:
    • 排名:千里之外
    • 原创:6篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章存档