ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

集合框架之HashMap(一)

2020-02-29 21:44:07  阅读:202  来源: 互联网

标签:HashMap 框架 int initialCapacity 链表 key 集合 hashMap


HashMap是非常重要的数据结构,并且大部分面试都会问到,优秀的java程序员应当要对HashMap进行深入的了解,今天我们就来剖析一下它。

目录

  • HashMap简介
  • 成员变量
  • get和put的流程
  • hashMap相关的面试题
  • 总结

一.简介

首先,HashMap是一个无序key,value集合,它的底层存储是由数组加链表和红黑树结构组成的的。在进行添加,删除和查找时,效率非常高,如果不考虑哈希碰撞,一次定位就能完成操作,时间复杂度为O(1)。
下面是一个默认长度的hashMap。

在这里插入图片描述

二.hashMap的成员变量

1.初始大小

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

这个是值是数组长度,也就是数组的初始最大行数,当然如果碰撞比较多,也有可能hashMap存了200个值,但是容量还是16。当然这不是理想状态。

2.最大值

static final int MAXIMUM_CAPACITY = 1 << 30;

这个没有什么好说的,hashMap最大容量。

3.增长因子

static final float DEFAULT_LOAD_FACTOR = 0.75f;

增长因子,就是如果数组被占用的大小超过当前大小的75%时,就进行扩容,按照当前容量二倍创建一个新的Entry,把旧Entry里的值重新hash计算,放到新的Entry里。

4.变树阈值

static final int TREEIFY_THRESHOLD = 8;

jdk8对hashMap做的优化,当链表长度大于8时,链表转换成红黑树,因为红黑树的查询效率是O(logn),
而链表的查询效率是O(n)

5.变链阈值

static final int UNTREEIFY_THRESHOLD = 6;

当红黑树总元素数小于6时,再转换成链表。因为红黑树元素太少时,效率比较低,所以转换成链表

三.HashMap的构造器

HashMap 提供了四个构造器,下面来一一看下。

1.HashMap()

使用默认的构造函数,构造一个初始容量为16,增长因子为0.75的空HashMap;

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
static final float DEFAULT_LOAD_FACTOR = 0.75f;

public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; 
}

2.HashMap(int initialCapacity, float loadFactor)

第一个参数是初始大小,第二个参数是增长因子,通过这两个参数来构造一个空的HashMap。

public HashMap(int initialCapacity, float loadFactor) {
    //判断容量是否小于0
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " +
                                           initialCapacity);
    //判断容量是否超过最大值
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    //判断加载因子
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " +
                                           loadFactor);
    this.loadFactor = loadFactor;
    //计算下一次resize的阈值
    this.threshold = tableSizeFor(initialCapacity);
}

3.HashMap(int initialCapacity)

一个参数的构造,通过初始增长因子构造一个空的HashMap,调用

HashMap(int initialCapacity, float loadFactor)构造方法。
public HashMap(int initialCapacity) {
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

4.HashMap(Map<? extends K, ? extends V> m)

根据已有的Map接口创建一个元素相同的hashMap,使用默认的初始容量和增长因子。
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR;
putMapEntries(m, false);
}

四.get和put方法

1.put方法

在HashMap插入值时,会判断是否已经初始化,如果没有初始化,就会创建一个长度为16的Entry,设置增长因子,默认为0.75。
然后判断key是否是Null,如果是Null则放到0处,如果不是,则对其key进行hash,实际操作是高位与低位混淆后做求余操作,然后,如果hash求出来的值与数组上的key值进行匹配,如果没有匹配上,则放到对应的数组bucket位置;如果与之前可以匹配上了(即为hash碰撞),则一一对比链表上的Key值是否相同,如果匹配上了则对当前位置的值进行修改,如果没有匹配的key,则放到该链表的尾部。

2.get方法

在hashMap进行get操作时,先判断key是否是null,如果是null则,直接取0处的bucket值,
如果不是则对key的hash值和数组上的每一个bucket的key的hash值对比没如果相同,则循环链表并对比key值是否相同,如果都相同,则返回该位置的value,如果没有相同的,则返回空。

五.HashMap相关的面试题

1.hashMap和hashtable区别
hashMap和Hashtable的内部结构基本一致,
1)hashMap支持null 作为key,但hashtable不支持;
2)HashMap是非线程安全的数据结构,所以相对来说,存取速度比较快;而Hashtable是线程安全的,因为hashtable的get、put等方法上添加了synchrounized的参数,对大部分方法上了排他锁,也就是说,在一个线程访问时其他线程都要等待。
但是如果数据量增大以后,HashTable的效率下降的比较快,所以如果你需要保证线程安全又要兼顾效率的话,从jdk1.6版本开始,java给提供了ConcurrentHashMap,它相对于hashtable的性能,做了优化,
它提出了分段锁机制, 它默认分8个段,操作开始时,先判断在那段内,然后操作时只锁定该段的数据,这样的话,只有访问同一个段的线程才回排队等待,访问不同段的线程之间互不冲突,这样来说,相对于hashtable对多线程的操作的效率提升了至少8倍,多线程并发操作效率得到了极大的提高。
2.Map<String,Object> map = new HashMap<>(20),问,该HashMap扩容了几次?
答:扩容了0次,因为它调用了HashMap的初始化方法,直接创建了一个长度为32的HashMap,而不是一个一个添加值,添加了20次,所以它只扩容了1次。
3.Map<String,Object> map = new HashMap<>(28),问,这条语句java虚拟机做了什么?
答:该语句创建了一个初始容量为64的空格的HashMap,为什么是64而不是32呢,因为它没有传加载因子,所以他的加载因子是0.75,28/32=0.875 ,已超过了0.75的阈值,所以自动扩容为当前的二倍,创建了一个长度为64的hashMap。

总结

今天对HashMap的实现原理进行了讲解,并对源码进行了分析,最后对比了hashMap和hashtable的区别,希望本篇文章能帮助到大家,同时也欢迎评论指正,谢谢支持!

慕容田雨 发布了19 篇原创文章 · 获赞 25 · 访问量 1万+ 私信 关注

标签:HashMap,框架,int,initialCapacity,链表,key,集合,hashMap
来源: https://blog.csdn.net/changxiangyangy/article/details/104582340

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有