Web基础算法专家

HashMap源码解析(直击面试焦点问题)

2018-09-07  本文已影响439人  第四风111

HashMap存储结构

  1. 数组你不是查询快吗,那我的哈希表就采用数组结构,即通过hash算法生成的哈希值即为哈希表中的存储位置。
  2. 链表你不是插入快吗,那我就存entry的时候利用链表插入,并解决了hash冲突的问题。

这里说明一下,前面数组是hash表,存放每一个链表的头指针;后面是链表结构。

HashMap用法

public static void main(String[] args) {
HashMap<Integer,String > map=new HashMap<>();
map.put(1, "张士超");
map.put(1, "张士超2");
map.put(4, "张士超4");
map.put(6, "张士超6");
System.out.println(map.get(1));
System.out.println(map.get(2));
System.out.println(map.keySet());
Iterator iterator=map.keySet().iterator();
while(iterator.hasNext()) {
    int key=(Integer)iterator.next();
    System.out.println(map.get(key));
}
}

HashMap的构造方法

HashMap有四种构造方法:

HashMap():构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空HashMap;
HashMap(int initialCapacity) :构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity, float loadFactor): 构造一个带指定初始容量和加载因子的空 HashMap。
HashMap(Map<? extends K,? extends V> m):构造一个映射关系与指定 Map 相同的新 HashMap。

HashMap存数据(put方法)

想要用HashMap存数据,要解决两个问题:

  1. 存在哪个位置;
  2. hash冲突怎么解决。
 int hash = hash(key);
 int i = indexFor(hash, table.length);

即通过当前的key生成hash值作为哈希表的数组存储位置,这里涉及到一个hash算法的问题,简单来说就是通过一系列的&、||、^和一些取余、取模运算,尽量使得计算的结果没有规律性可循。

entry<"2","2">——>entry<"1","1">

这里说明一下,假设现在我又存一个数据entry<"1","2">,这个数据会不会直接插在表头呢,不会的,他会更新之前的entry<"1","1">数据,具体是比较key的hash()和equal()方法,如果都相等,证明是一个entry,此时变成了:

entry<"2","2">——>entry<"1","2">

hashmap取数据(get方法)

int hash = (key == null) ? 0 : hash(key);
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 != null && key.equals(k))))
        return e;
}
  1. 我们之前说过的,链表查询速度慢,所以链表长度的默认阈值为8,当长度超过8时,则会采用红黑树的结构来提高遍历效率(jdk1.8以上),结构如下:


    数组+链表+红黑树

HashMap多线程问题

1.由于HashMap不是线程安全的,所以多线程的put存数据肯定会存在问题,可能造成存错、存空等问题。
2.多线程造成循环列表、导致get死循环,简单来说,就是两个线程那个同时对hash表进行扩容处理(rehash处理),导致链表很容易产生回路,然后在get操作时产生死循环!


多线程造成的链表死循环.png
  1. 改进方法就是在多线程中用ConcurrentHashMap或者HashTable代替HashMap。

HashMap与LinkedHashMap的区别与联系

  1. LinkedHashMap是HashMap的子类,HashMap有的方法LinkedHashMap都有,都是数组+链表的存储结构,但与HashMap不同的是,链表双向循环链表,它可以做到有序。
  2. 因为双向循环链表的存在,LinkedHashMap可以记录数据插入的顺序。

创作不易,交出你的小心心!!!!!!!!!!!!!!!!!

上一篇 下一篇

猜你喜欢

热点阅读