Java 学习笔记(十)

List

ArrayList

  • 底层维护一个 Object 类型的数组 elementData[],所以可以放任意类型的元素 transient Object[] elementData,其中 transient 表示该属性不会被序列化
  • 创建 ArrayList 对象时,如果使用无参构造器,那么初始容量为 0,第一次添加扩容为 10,如果需要再次扩容,则扩充容量为当前的 1.5 倍
  • 如果使用指定大小的构造器,那么初始容量就为指定的大小,如果需要再次扩容,则扩充容量为当前的 1.5 倍
  • 线程不安全

Vector

  • 底层也是一个对象数组 protected Object[] elementData
  • Vector 是线程同步的,即线程安全
  • 扩容机制和 ArrayList 类似,不过是每次容量不足时扩容为当前的 2 倍

LinkedList

  • 实现了双端队列和双向链表的特点。底层维护了一个双向链表,有两个指针(first, last)分别指向了首尾节点
  • 每个节点里面又维护了 prev、next、item 三个属性
  • 添加和删除不是通过数组完成的,效率高;查询和更改的效率低
  • 可以添加任意元素,包括 null
  • 线程不安全

Set

特点:

  • 存放数据是无序的(不是添加的顺序),但是是一个固定的状态(即每次取出都是一样的顺序)
  • 不能存放重复元素

HashSet

  1. 实现了 Set 接口,但实际上是 HashMap(构造器中 new 了一个 HashMap),底层是 数组 + 单链表
  2. 不保证数据元素有序,取决于 hash 后确定的索引
  3. 线程不安全

底层添加机制

  1. 添加元素时,先算出 hash 值
  2. 根据 hash 值找存储数据表的对应位置,查看是否有元素
  3. 若没有元素直接插入,添加完成。若有元素,进入下一步
  4. 调用 equals 比较,如果相同,放弃添加;如果不相同,插到当前链表尾部

底层扩容机制

  1. 初始时 table 数组(存储元素的表)大小为 16,临界值为 12(加载因子 0.75 * 16)
  2. 如果 table 使用了 12 个元素,也就是达到临界值,就会扩容到 16 * 2,新的临界值就是 24 ,以此类推

在 Java 8中,如果一条链表的长度到达 TREEIFY——THRESHOLD(默认 8),并且 table 大小 >= MIN_TREEIFY_CAPACITY(默认 64),就会进行树化(红黑树)

LinkedHashSet

  • 是 HashSet 的子类
  • 底层实现是 LinkedHashMap,底层维护了一个 数组 + 双链表。其中,数组是 LinkedHashMap$Node[]
  • 存放的节点类型是 LinkedHashMap$Entry,而 Entry 是一个静态内部类
  • 根据 hash 值确定存储位置,通过链表保证元素的插入次序
  • 线程不安全

TreeSet

  • 会对集合内的元素排序,底层使用的是 TreeMap
  • 默认升序,可以在初始化的时候添加比较器(匿名内部类,指定排序规则)

Map

  • 用于保存 key-value 对,其中 key 和 value 可以是任意类型的对象,会被封装成 HashMap$Node
  • key 不允许重复
  • value 可以重复
  • key 和 value 之间存在一对一对应,一对 key-value 放在一个 Node 中,因为 Node 实现了 Entry 接口,所以也说一对 key-value 就是一个 Entry(遍历时会有 entrySet 或者 keySet 或者 values 方法,获取对应的集合,集合内容其实就是对 HashMap$Node 节点的引用)

遍历方法

  1. 获取 keySet 使用增强 for
  2. 使用 keySet 迭代器获取 key,get 方法获取 value
  3. 获取 values,使用增强 for
  4. values 的迭代器
  5. 获取 entrySet,使用增强 for 遍历(常用)
  6. entrySet 的迭代器

HashMap

  • 线程不安全
  • key 和 value 都可以为 null,不过只能有一个 key 为 null
  • 底层机制与 HashSet 基本相同

LinkedHashMap

  • HashMap 的子类
  • 底层机制与 LinkedHashSet 基本相同

TreeMap

  • 与刚刚提到的 TreeSet 类似

Hashtable

  • key 和 value 都不可以为 null
  • 线程安全
  • 方法和 HashMap 基本一致
  • 底层有数组 Hashtable$Entry ,初始化大小为 11,临界值为 11 * 0.75 约等于 8。
  • 当容量(每次添加节点后容量才 +1)大于等于临界值时进行扩容(扩容比较在添加新节点前),扩容方法为 旧的容量 * 2 + 1

Properties

  • 继承自 Hashtable
  • Properties 可以从 xxx.properties 文件中加载数据到 Properties 类的对象中
  • xxx.properties 文件通常为配置文件

对比总结

底层用数组实现的

  • ArrayList,底层维护一个 Object 类型的数组 elementData[],所以可以放任意类型的元素

数组 + 单链表

  • HashSet
  • HashMap

数组 + 双链表

  • LinkedHashSet
  • LinkedHashMap

可以添加 null 作为元素的

  • ArrayList,底层将 null 转换为 “null”
  • LinkedList
  • Vector
  • HashSet,不过只能放一个
  • HashMap key 和 value 都可以为 null,不过只能有一个 key 为 null

线程不安全的

  • ArrayList
  • LinkedList
  • HashSet
  • LinkedHashSet
  • HashMap

线程安全的

  • Vector
  • Hashtable
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三更鬼

谢谢老板!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值