HashMap浅析

来源:互联网 发布:iphone6没有4g网络 编辑:程序博客网 时间:2024/05/16 01:13

jdk中为我们提供了大量好用的工具类HashMap就是其中之一。HashMap是基于哈希表的 Map 接口的实现,因为其经典的设计结构而成为面试的必考部分。


首先介绍他的使用特性:HashMap用来存储制定的键值对,允许使用 null 值和 null 键且键值对没有顺序。


下面开始介绍HashMap的实现,从而解释为什么HashMap有以上特性。

首先HashMap从名字大致可以听出HashMap是由Hash表实现的下面我们先来介绍一下hash表


从上图我们可以发现哈希表是由数组+链表组成的,那么这些元素是按照什么样的规则存储到数组中呢。

一般情况是通过hash(key)获得相应的hashcode值再用hashcode%数组长度,取得的余数就是这个元素在数组中的存储位置但是如果遇到余数相等的情况该怎么办呢?比如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都存储在数组下标为12的位置。这时我们就要用拉链法通过链表将元素串起来在将链表头结点存放在相应数组位置。但是会影响我们取值时的搜索时间,因为当链表很长时,我们为了搜索到对应的链表元素就必须要对链表逐个扫描,这是很费时间的。所以hash(key)算法要尽量算的均匀。


具体hash表中的存放规则说完了回过头说一下hashmap。

首先HashMap有如下实现方法


    /**
     * The default initial capacity - MUST be a power of two.
     */

    static final int DEFAULT_INITIAL_CAPACITY = 16;

    /**
     * The maximum capacity, used if a higher value is implicitly specified
     * by either of the constructors with arguments.
     * MUST be a power of two <= 1<<30.
     */

    static final int MAXIMUM_CAPACITY = 1 << 30;

    /**
     * The load factor used when none specified in constructor.
     */

    static final float DEFAULT_LOAD_FACTOR = 0.75f;

    /**
     * The table, resized as necessary. Length MUST Always be a power of two.
     */

    transient Entry[] table;


我们可以看到在new hashmap时可以指定初始容量和装载因子,它们的初始值分别为16与0.75这两个值分别代表什么呢?

初始容量即设定好初始hash表的数组长度。在hashmap中默认为十六(DEFAULT_INITIAL_CAPACITY = 16;)。装载因子为确定何时容器开始扩容的标准(DEFAULT_LOAD_FACTOR = 0.75f;),具体怎么做呢、假设我们有一个初始长度为十六的hashmap容器。我们都知道,容器是可以根据存入数据的个数自动扩充长度的。hashmap的扩充规则是初始长度 × 装载因子 = 最大存储量 当容器中存入元素的格式大于这个值时hashmape长度自动扩充一倍 即16 × 2 = 32 但是我们既然数组的长度增加,了那么之前进行存储的元素就需要再重新按之前的规则重新计算存储。这个过程被称为再散列。再散列是很消耗运算资源的所以我们要尽量避免。比如可以人为吧初始长度安适当长度设置。(注意设置的长度一般是2^n具体原因以后在其他的文章中介绍。)

1 0