java集合与底层实现(下)

Map集合

将键映射到值得对象,一个映射不能包含重复的键,每个键只能映射到一个值,map集合存储元素是成对出现的。map集合的数据结构针对键有效,跟值无关。常用子类(HashMap、linkedHashMap、TreeMap、ConcurrentHashMap)
map常用方法

map涉及数据结构

散列图

链表和数组要获取某个元素,就要访问所有的元素,直到找到为止,散列图不在意元素的顺序,能够快速的查找元素的数据。哈希表本质是一个数组,数组中每一个元素称为一个箱子bin,箱子中存放键值对。哈希表的存储过程如下:

  1. 根据key计算出它的哈希值h(高16位进行异或操作
  2. 假设箱子的个数是n,那么键值对应该放在第(h % n)个箱子里
  3. 如果该箱子已经有了键值对,则使用开放寻址法或者连地址法解决冲突
    负载因子体现哈希表的空满程度,当大于某个常数时(0.75),哈希表将自动扩容
红黑树

红黑树:是一种平衡二叉树,在插入数据时也在保持树的平衡(任何节点的两个子树高度差<=1),使用旋转、反色方式实现。

HashMap 无序,允许为null,线程不安全

底层:数组+链表(散列表)+红黑树
  • 散列表的属性装载因子:默认值为0.75 当装载因子*初始容量小于散列元素时,散列表会再散列,扩容两倍。
    装载因子大———导致散列冲突可能性变大
    装载因子小 ———扩容次数变大
  • 初始容量:默认值为16
    初始容量大———遍历时速度会受影响
    初始容量小———扩容的次数就变多
  • 哈希值:hashMap并不是直接拿key的哈希值来用的,它将key的哈希值高16位进行异或操作,使得我们将元素放入哈希表的时候增加了一定的随机性
  • 红黑树节点:桶子上有8位元素的并且散列表容量大于64,就从链表变成红黑树
    在这里插入图片描述

LinkedHashMap

底层:散列表+双向链表(插入的顺序是有序的)

遍历顺序:访问顺序和插入顺序(默认)

TreeMap

底层:红黑树,有序,线程不安全
  • Comparator:如果构造方法里传入Comparator对象,就以这个对象的方法进行比较,否则使用Comparable的compareTo(T 0)方法(自然排序)比较。
  • key不能为空

ConcurrentHashMap

底层:散列图+红黑树
  • 线程安全:ConCurrentHashMap支持高并发的访问和更新,它是线程安全的
    通过部分加锁和利用CAS算法来实现同步
  • CAS算法
    当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值(A和内存值V相同时,将内存值V修改为B),而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试(否则什么都不做)
  • volatile关键字
    保证该变量对所有线程的可见性,在多线程的环境下:当这个变量修改时,所有的线程都会知道该变量被修改了,也就是所谓的“可见性”。不保证原子性,修改变量(赋值)实质上是在JVM中分了好几步,而在这几步内(从装载变量到修改),它是不安全的。
  • get方法:是非阻塞的,无锁,通过volatile修饰next来实现每次获取都是最新的设置的值
  • key和value都不允许为null

猜你喜欢

转载自blog.csdn.net/qq_36741161/article/details/88429423
今日推荐