Java HashMap 源代码分析

概述

  HashMap是Java中的常用工具,位于java.util包里面。本文分析的Java SDK版本是1.8,在key冲突严重的时候,会使用红黑树进行优化。HashMap允许null作为key和value值,并且不是线程安全的,这是和HashTable不同的地方。如果需要线程安全的哈希表,推荐使用ConcurrentHashMap,而不是HashTable。另外,此实现不保证有序(如需要,请使用TreeMap)。

  本文从常用的操作作为切入点,来分析HashMap的实现原理,着重分析几个重要的操作逻辑实现函数。对于红黑树的部分、iterator等部分不去展开论述。

  HashMap的源代码大概有2000多行(1.8),但是,只要根据源代码中的注释,就可以清晰的分为:Static utilities, Fields, Public operations, iterators, spliterators, Tree bins等部分,我们会着重讨论Public operations部分,因为这里是其逻辑实现的核心。

实现原理简述

  首先讲一下HashMap的基本实现原理。我们都知道HashMap是一个key、value构成的一个表,常用的两个操作是getput。HashMap很依赖对象的hashcode方法:在进行任何操作之前,都会先用hashcode计算HashMap内部所对应的hash。HashMap内部有一个数组,在计算出hash之后会和数组的size(HashMap初始化时的capacity)进行位与操作,计算其在数组中的index,找到所在的。(桶一般是个list,如果比较长(默认大于8)会转化为红黑树。)如果是get,查找等于key的值返回;put则将值插入合适的位置。

几个概念说明

工具函数

重要函数

总结

  本文分析了Java1.8 HashMap源代码实现,着重对其设计思想、实现逻辑进行介绍。其中,对put、get、remove等基本操作的内部实现函数进行了详细剖析。但是,对于红黑树部分没有做任何介绍,因为红黑树本身实现比较繁琐,我们这里只需要它是个平衡二叉树即可(对于其实现细节的旋转、插入、删除需要单独做介绍,不是本文的重点)。另外,1.8版本的代码中加入了spliterator遍历器,以及加入了Function接口。对于这部分本文也没有涉及(比较简单,看代码很容易明白,也非核心逻辑)。