知识梳理_03_Java集合

结构

在这里插入图片描述

参考

https://mp.weixin.qq.com/s/bVOSat47L0Hskfx9akAN6Q
https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/Java%E9%9B%86%E5%90%88%E6%A1%86%E6%9E%B6%E5%B8%B8%E8%A7%81%E9%9D%A2%E8%AF%95%E9%A2%98.md

List

有序,可重复

ArrayList

参考:
https://github.com/Snailclimb/JavaGuide/blob/master/docs/java/collection/ArrayList%E6%BA%90%E7%A0%81+%E6%89%A9%E5%AE%B9%E6%9C%BA%E5%88%B6%E5%88%86%E6%9E%90.md
https://mp.weixin.qq.com/s/WoGclm7SsbURGigI3Mwr3w

特点

查询效率高,遍历效率高,增删效率低(需要大量移动元素),线程不安全

  • 底层结构
    Object[]数组

容量大小

以无参数构造方法创建 ArrayList 时,实际上初始化赋值的是一个空数组。当真正对数组进行添加元素操作时,才真正分配容量。即向数组中添加第一个元素时,数组容量扩为 10
在这里插入图片描述
在这里插入图片描述

扩容

每次扩容之后容量都会变为原来的 1.5 倍左右(oldCapacity 为偶数就是 1.5 倍,否则是 1.5 倍左右)!
在这里插入图片描述

新增和删除使用的是Copy

在这里插入图片描述
在这里插入图片描述

Vector

  • 特点
    线程安全,效率低
  • 底层结构
    Object[]数组
  • 扩容
    每次扩容之后容量都会变为原来的 2倍左右
    在这里插入图片描述

LinkedList

  • 特点
    查询效率低,遍历效率低,增删效率高,线程不安全
  • 底层结构
    双向链表

Set

无序,不重复

HashSet

  • 特点
    添加速度快,查询速度快,删除速度快,无序
  • 底层结构
    采用 Hashmap 的 key 来储存元素;
    数值放在 map 中的 key 上,value 上放了个 PRESENT,是一个静态的 Object,相当于 place holder,每个 key 都指向这个 object。

TreeSet

  • 特点
    有序,查询速度(按照内容查询)比List快,查询速度没有HashSet快
  • 底层结构
    红黑树

LinkedHashSet

  • 特点
    有序
  • 底层结构
    HashSet + LinkedList 的结构

Map

Key-Value映射

HashMap

特点

线程不安全,使用key,value结构存储数据

底层结构

JDK1.7:数组(初始容量默认为16)+链表
JDK1.8:数组(初始容量默认为16)+链表+红黑树(默认当链表长度达到8的时候会转换成红黑树)

JDK1.8 PUT过程

在这里插入图片描述

加载因子

默认0.75
加载因子越小,容易扩容,浪费空间,但查找效率高 链表特别短 减少hash冲突
加载因子越大,不易扩容,对空间的利用更加充分,查找效率低(链表拉长)hash冲突比较多,链表比较长

扩容

  1. 什么时候扩容
    现有容量 >总容量 × 负载因子 的时候进行扩容
    例如:给定的默认容量为 16,加载因子为 0.75。Map 在使用过程中不断的往里面存放数据,当数量达到了 16 * 0.75 = 12 就需要将当前 16 的容量进行扩容
  2. 如何扩容
    分为两步
    扩容:创建一个新的Entry空数组,长度是原数组的2倍
    ReHash:遍历原Entry数组,把所有的Entry重新Hash到新数组。

扩容时死循环问题

JDK1.7:采用头插入法,会改变链表的顺序,在多线程操作的情况下,可能出现环形链表,造成死锁
JDK1.8:采用尾插入法,在扩容时会保持链表元素原本的顺序,就不会出现链表成环的问题了。

为什么初始容量是2的n次幂

首先看下index的计算公式:index = HashCode(Key) & (Length- 1)
在这里插入图片描述

ConcurrentHashMap

参考:
https://mp.weixin.qq.com/s/AHWzboztt53ZfFZmsSnMSw
https://mp.weixin.qq.com/s/AixdbEiXf3KfE724kg2YIw

特点

线程安全

  • JDK1.7
    使用分段锁,使用CAS+Unsafe+ReentrantLock+Volatile,Segment 继承了 ReentrantLock

  • JDK1.8
    没有分段锁,使用CAS+Unsafe+Synchronized+Volatile

底层结构

  • JDK1.7
    Segment 数组 + HashEntry 数组 + 链表,每个 Segment 里边是由 HashEntry 组成的数组,每个 HashEntry之间又可以形成链表。我们可以把每个 Segment 看成是一个小的 HashMap,其内部结构和 HashMap 是一模一样的。所以每一个 HashMap 的内部可以进行扩容。但是 Segment 的个数一旦初始化就不能改变,默认 Segment 的个数是 16 个,你也可以认为 ConcurrentHashMap 默认支持最多 16 个线程并发

  • JDK1.8
    Node 数组 + 链表 / 红黑树

PUT操作

  • JDK1.7
    在这里插入图片描述
  • JDK1.8
    在这里插入图片描述

HashTable

线程安全,get 和put 都会用 synchronized 关键字加锁。
Hashtable 初始容量为:11,负载因子默认都是:0.75。
Hashtable 扩容规则为当前容量翻倍 + 1。

TreeMap

红黑树(自平衡的排序二叉树),有序

LinkedHashMap

有序的HashMap

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值