墨烯的Java技术栈-Java容器-009

Java容器最后一篇

一.源码分析

java.util包中

(1)ArrayList

基于数组织实现的,支持快速范围,RadomAccess接口标识着该类支持快速随机范围

数组默认大小为10

扩容 不够时grow()方法扩容大小为之前的1.5倍左右

扩容是把原数组整个复制到新数组,这个操作代价很高.因此最好创建时候就指好容量大小

删除元素从index+1到index位置上,该时间复杂度操作为O(N),可以看到ArrayList删除元素的代价非常高

基于数组实现,并且有动态扩容特性,因此保存元素的数组不一定都会被使用,那么就必要全部进行序列化

保存元素的数组elemenData使用transient修饰,该关键字声明数组默认不会被序列化

(2)Vector

它的实现与 ArrayList 类似,但是使用了 synchronized 进行同步

Vector 的构造函数可以传入 capacityIncrement 参数,它的作用是在扩容时使容量 capacity 增长 capacityIncrement。如果这个参数的值小于等于 0,扩容时每次都令 capacity 为原来的两倍

调用没有 capacityIncrement 的构造函数时,capacityIncrement 值被设置为 0,也就是说默认情况下 Vector 每次扩容时容量都会翻倍。

与ArrayList相比

Vector 是同步的,因此开销就比 ArrayList 要大,访问速度更慢。最好使用 ArrayList 而不是 Vector,因为同步操作完全可以由程序员自己来控制

Vector 每次扩容请求其大小的 2 倍,而 ArrayList 是 1.5 倍。

(3)CopyOnWriteArrayList

写操作在一个复制的数组上进行,读操作还是在原始数组中进行,读写分离,互不影响

CopyOnWriteArrayList 在写操作的同时允许读操作,大大提高了读操作的性能,因此很适合读多写少的应用场景

内存占用:在写操作时需要复制一个新的数组,使得内存占用为原来的两倍左右

数据不一致:读操作不能读取实时性的数据,因为部分写操作的数据还未同步到读数组中

(4)LinkedList

基于双向链表实现

每个链表存储了 first 和 last 指针

与ArrayList比较

数组支持随机访问,但插入删除的代价很高,需要移动大量元素

链表不支持随机访问,但插入删除只需要改变指针

就是用来专门插入删除的数组

(5)HashMap

内部包含了一个 Entry 类型的数组 table。Entry 存储着键值对

新建一个 HashMap,默认大小为 16

查找分两步

计算键值对所在的桶

在链表上顺序查找,时间复杂度显然和链表的长度成正比

HashMap 允许插入键为 null 的键值对 但是无法调用 null 的 hashCode() 方法

使用链表的头插法,也就是新的键值对插在链表的头部

(6)ConcurrentHashMap

ConcurrentHashMap 和 HashMap 实现上类似,最主要的差别是 ConcurrentHashMap 采用了分段锁

默认的并发级别为 16,也就是说默认创建 16 个 Segment

每个 Segment 维护了一个 count 变量来统计该 Segment 中的键值对个数

(7)LinkedHashMap

继承自 HashMap,因此具有和 HashMap 一样的快速查找特性

内部维护了一个双向链表

LinkedHashMap 最重要的是以下用于维护顺序的函数,它们会在 put、get 等方法中调用

(8)WeakHashMap

WeakHashMap 主要用来实现缓存,通过使用 WeakHashMap 来引用缓存对象,由 JVM 对这部分缓存进行回收

Tomcat 中的 ConcurrentCache 使用了 WeakHashMap 来实现缓存功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值