凡是所有的java面试中,一般问到数据结构,基本上都会问到数组,集合等这样的数据结构,然后HashMap是经常被问到的,今天我们就聊一聊这个hashmap,以及我常常面试被问到关于hashmap这一块,多总结,多实践,最后就可以对这一块比较熟悉了。
首先我们要知道什么是HashMap
1.HashMap的定义
HashMap是用哈希表(直接一点可以说数组加单链表)+红黑树实现的map类。
2.HashMap的特点
1.底层实现是 链表数组,JDK 8 后又加了 红黑树
2.实现了 Map 全部的方法
3.key 用 Set 存放,所以想做到 key 不允许重复,key 对应的类(一般是String)需要重写 hashCode 和 equals 方法
4.允许空键和空值(但空键只有一个,且放在第一位,知道就行)
5.元素是无序的,而且顺序会不定时改变(每次扩容后,都会重新哈希,也就是key通过哈希函数计算后会得出与之前不同的哈希值,这就导致哈希表里的元素是没有顺序,会随时变化的,这是因为哈希函数与桶数组容量有关,每次结点到了临界值后,就会自动扩容,扩容后桶数组容量都会乘二,而key不变,那么哈希值一定会变)
6.插入、获取的时间复杂度基本是 O(1)(前提是有适当的哈希函数,让元素分布在均匀的位置)
7.遍历整个 Map 需要的时间与数组的长度成正比(因此初始化时 HashMap 的容量不宜太大)
8.HashMap不是同步,HashTable是同步的,但HashTable已经弃用,如果需要线程安全,可以用synchronizedMap,
例如 Map m = Collections.synchronizedMap(new HashMap(...));
3.HashMap的工作原理是什么?
HashMap是基于hashing的原理,我们使用put(key, value)存储对象到HashMap中,
使用get(key)从HashMap中获取对象。当我们给put()方法传递键和值时,
我们先对键调用hashCode()方法,
计算并返回的hashCode是用于找到Map数组的bucket位置来储存Node 对象。
这里关键点在于指出,HashMap是在bucket中储存键对象和值对象,作为Map.Node 。
好了,以上三点搞清楚了,我觉得起码认识很好了,然后针对性的做一些对比,去拓展一些相对的,比如hashtable 等。
一般到这个时候,面试官就会问,你平时对这个HashMap怎么用的,你是怎么存取值得呢?你说说下底层原理实现吧,这个一般才是考你的重点(个人认为)
put过程:
put过程(JDK1.8版)
1.对Key求Hash值,然后再计算下标
2.如果没有碰撞,直接放入桶中(碰撞的意思是计算得到的Hash值相同,需要放到同一个bucket中)
3.如果碰撞了,以链表的方式链接到后面
4.如果链表长度超过阀值( TREEIFY THRESHOLD==8),就把链表转成红黑树,链表长度低于6,就把红黑树转回链表
5.如果节点已经存在就替换旧值
6.如果桶满了(容量16*加载因子0.75),就需要 resize(扩容2倍后重排)
get过程(考虑特殊情况如果两个键的hashcode相同,你如何获取值对象?)
当我们调用get()方法,HashMap会使用键对象的hashcode找到bucket位置,
找到bucket位置之后,
会调用keys.equals()方法去找到链表中正确的节点,
最终找到要找的值对象。
ok 到这里 ,你再去延伸什么CocurrentHashMap等,那样聊的就多了 这一块岂不是就聊的很好啦。