hashmap判断key相等_Java1.8的HashMap源码分析面试必备技能

  • java1.8是现在用的最多的版本,HashMap是现在用的最多的map,HashMap的源码可以说是面试必备技能,今天我们试图分析一下源码。

  • 之前我们分析java1.7的hashMap说它有一个问题,链表过长,java8引入了红黑树解决

  • 结构:数组加链表,链表过长时裂变为红黑树

01f60aa3ea654de7b3eff06d7c7e368e.png

一、先看整体的数据结构

首先我们注意到数据是存放在一个Node数组里面

transient Node[] table;

接着我们看一下Node的结构

    static class Node implements Map.Entry {
    
final int hash;
final K key;
V value;
Node next;
Node(int hash, K key, V value, Node next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry,?> e = (Map.Entry,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}

我们注意到这是一个单链表,next指向下一个节点。

二、我们先看简单的get方法

接着我们看一下get(Object key)方法

    public V get(Object key) {
    
Node e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}

实际调用的getNode方法

    final Node getNode(int hash, Object key) {
    
Node[] tab; Node first, e; int n; K k;
if ((tab = table) != null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) != null) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}

我们来一步步分析,首先定位到数据在数组的下标:(n - 1) & hash
找到数组的第一个node:first

first = tab[(n - 1) & hash]

如果first为null直接返回 如果first的key和get里面的key相等,则返回first的value

if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;

如果first的key和get里面的key不相等,判断first是不是TreeNode,如果不是,则一直找链表的next,直到key和所传的key相等

do {
    
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);

如果first的key和get里面的key不相等,判断first是不是TreeNode,如果是,则调用getTreeNode方法查找

 if (first instanceof TreeNode)
return ((TreeNode)first).getTreeNode(hash, key);

我们看一下TreeNode的数据结构

static final class TreeNode extends LinkedHas
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值