数据结构
最核心的其实就是数据结构,那具体是什么呢?
三大核心数据结构:数组 + 链表 + 红黑树。
看架构图
1.上面一行是数组
这种情况是key的hash取模的值不重复。
2.竖着的两列是模值重复的情况
1)即有可能是链表
链表的数据数量大于8,就会自动转换为红黑树。
2)也有可能是红黑树
数组
先看数组,数组的作用是,key的hash进行取模,这个模的值就是数组索引,key/value这个Node就存储到这个索引的位置。
如果取模的值一样怎么办?不一样的key,取模可能得到不一样的值,那怎么存储呢?
这个时候,就得用链表,详细见下文。
Node类
存储了key/value,看源码:java.util.HashMap.Node
static class Node<K,V> implements Map.Entry<K,V> {
final int hash; //key的hash
final K key; //存储了key/value
V value;
Node<K,V> next;
这里再注意一下几个数据:
1、 key
2、 key的hash
3、 hash取模
这个对应数组索引
4、 key/value到底存储在哪里?
key/value本身是存储在Node节点。
但是怎么把这些Node节点,即不同的key/value给组装起来呢?这个时候,就需要数据结构。什么数据结构?数组。所以,Node类存储了key/vaue的值,数组这个数据结构把不同的key/value给关联起来。一个是存储值,一个是存储关系。
链表
刚才说到,模值一样,就要用到链表。所以,链表要解决的问题,就是模值一样的key,到底怎么存储。
其实就是用链表,说白了,就是往链表后面插数据即可。
写的时候,是往后面插。那读的时候,怎么读呢?既然模值都一样,那怎么知道哪个key对应哪个value呢?
其实是可以的,别慌,其实就是两步:
1、 先找到模值,即数组的索引
2、 如果索引一样,继续找到key值
注意这里,key值是不一样的。我们前面说的是,不同的key,模值一样,但是请注意,模值一样,key不一样。所以,我们比较的时候,就是先比较模值,如果模值一样,再比较key值,这样就可以找到那个key对应的value。
核心点:找模值/索引的时候,是在数组里找。找key值的时候,是在链表里找。
到目前为止,好像问题都解决了,即模值不一样,就存储在数组,模值一样,就存储到链表。那为什么还需要红黑树呢?
知识点来了,链表是为了解决模值重复/冲突的问题,而红黑树是为了解决高性能的问题。
怎么说?链表的读速度很慢,即遍历速度很慢,因为是顺序遍历。所以,如果链表的数据很多的话,那么读速度就很慢,说白了,就是map的查找数据很慢,那怎么解决呢?红黑树。
树要解决的问题,就是综合了数组和链表的优点,即读速度很快,写速度也很快。
最后总结一下,具体来说,就是链表的数据如果超过8,那么就自动转换为树;如果树的数据后面因为删除又变少了,那么又会自动转换为链表。反正就是可以互相转换。
最后再注意一下,节点和树节点有点不一样,使用的是不同的类。
参考
java高并发和集合框架