先来回顾一下Map类中常用实现类的区别:

HashMap:底层实现是哈希表+链表,在JDK8中,当链表长度大于8时转换为红黑树,线程不安全,效率高,允许key或value为null

HashTable:底层实现是哈希表+链表,线程安全,效率低,不允许key或value为null(现在不推荐使用)

TreeMap:底层实现是红黑树,即可按照键的大小排序,如果是自定义的类,可以通过实现Comparator接口重写compare方法

为了更好的理解,建议先对数据结构中链表和哈希表有一个认识^ ^

通俗来说哈希表就是通过一个哈希函数将当前元素的关键字映射到数组中的一个存储位置。

即 存储位置 = f(关键字),其中f即为哈希函数。

因为存储空间有线,我们这个函数不可能做到输入任意元素都能得到不同的存储位置,所以当两个不同的元素通过哈希函数得到了相同的存储地址时,就出现了哈希冲突,这里的链表就是为了解决哈希冲突存在的,我们可以将相同地址的元素以链表的形式存储在相应的位置。HashMap就是运用了这种链表+数组的方式。即如下图所示。

然后我们来一点一点分析HashMap的源码。

HashMap的主干是一个Node数组,每一个Node包含一个key-value键值对。

// table即为HashMap的主干数组,该数组长度为2的次幂
transient Node<K,V>[] table;

我们可以再来看一下Node的源码。可以看到每个Node都是由一个hash值、k-v键值对、next引用(指向下一个Node)构成。

    static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;     // 下面的不是很关键,我们主要关注Node的结构
Node(int hash, K key, V value, Node<K,V> 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;
}
}

  

了解了HashMap的内部结构,我们就先来看看简单一点的get方法。

从这里可以看到get函数很简单,就是通过获取所需要查询元素的哈希值找到节点,然后返回节点的value,所以其中关键就是getNode函数。

    public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
    final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> 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<K,V>)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;
}

  

最新文章

  1. Spring--多人开发
  2. window下 Sublime Text 3 安装
  3. DayPilot 7.8 DLL去DEMO字样下载
  4. 使用.net Stopwatch class 来分析你的代码
  5. Hadoop生态上几个技术的关系与区别:hive、pig、hbase 关系与区别
  6. 发送SMS短信(JSON) 转载
  7. Log4Cplus的介绍
  8. window IIS6/IIS7取消脚本执行权限,禁止运行脚本木马
  9. Exploring the Angular 1.5 .component() method
  10. ubuntu 14.04 下FTP服务器的搭建--锁定用户目录,解决vsftpd: refusing to run with writable root inside chroot()
  11. phpcms v9修改栏目描述的多行文本为编辑器方法
  12. uva 1103
  13. 使用graphics2D给图片上画字符
  14. java在的数据类型
  15. XP和win7的软件崩溃提示
  16. Git的思想和基本工作原理2
  17. SVN用户切换
  18. 进程间通信IPC机制和生产者消费者模型
  19. [c][c++]按位操作
  20. retrofit2 不创建对象直接返回字符串

热门文章

  1. 求第n行杨辉三角(n很大,取模
  2. keras自定义网络层
  3. PM2 All In One
  4. javascript nested object merge
  5. js &amp; array &amp; shuffle
  6. 如何取消 Google Cloud Platform 试用 &amp; 关闭 GCP 帐号 &amp; 删除信用卡 &amp; 取消订阅
  7. Dart: 执行shell命令
  8. (数据科学学习手札108)Python+Dash快速web应用开发——静态部件篇(上)
  9. Python3网络爬虫-- 使用代理,轮换使用各种IP访问
  10. 聊聊CPU的LOCK指令