学习目标
- 线性表
- 顺序表与链表的简单了解
- ArrayList的介绍
- ArrayList的扩容机制
-
线性表
线性表(linear list): 是由n且具有相同的特性数据元素的有限列表, 线性表在实际运用中常见的数据结构, 常见的线性表: 栈 , 堆 , 队列 , 顺序表 , 链表…
链表:在逻辑上是连续的数据结构, 但在物理结构上不一定是连续的, 用顺序表和链表实现线性表时可以明显观察出区别.
2,顺序表
顺序表是在物理上是用一段连续的物理内存保存数据元素的线性结构, 一般情况下使用数组储存. 在数组上完成增删改查.
链表是在逻辑上保存数据元素的线性结构, 每个数据元素可能分布在内存的各个地方 ,主要通过next找到下个元素数据.
3 ArrayList简介
在集合框架中 ArrayList是一个普通类, 实现了List接口
【说明】
1. ArrayList是以泛型方式实现的,使用时必须要先实例化
2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
3. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
5. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可
选择Vector或者
6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表\
3.1 ArrayList的构造方法
3.2ArrayList 的常见操作
ArrayList提供的方法有诸多,但我们只需掌握常见方法即可
4 . ArrayLists的扩容机制
此处的下面代码能否执行?为什么?
ArrayList是一个动态类型的顺序表, 在插入数据时会检查数组大小, 当数组满时会进行自动扩容
ArrayList的部分源码
Object[] elementData; // 存放元素的空间
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空间
private static final int DEFAULT_CAPACITY = 10; // 默认容量大小
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
// 获取旧空间大小
int oldCapacity = elementData.length;
// 预计按照1.5倍方式扩容
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果用户需要扩容大小 超过 原空间1.5倍,按照用户所需大小扩容
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if(newCapacity - MAX_AEEAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//调用copyOf扩容
elementData = Arrays.copyOf(elementData , newCapacity);
}
private static int hugeCapacity(int minCapacity){
// 如果minCapacity小于0 ,抛出OutOfMemoryError异常
if(minCapacity < 0)
throw new OutOfMemoryError();
retur (minCapacity > MAX_AEEAY_SIZE)? lnterger.MAX_VALUE:MAX_ARRAY_SIZE;
}
}
总 结 :
1. 检 测 是 否 真 正 需 要 扩 容 , 如 果 是 调 用 g r o w 准 备 扩 容
2. 预 估 需 要 库 容 的 大 小 初 步 预 估 按 照 1.5 倍 大 小 扩 容 如 果 用 户 所 需扩容的 大 小 超 过 预 估 1.5 倍 大 小 , 则 按 照 用 户 所 需 大 小 扩 容 , 真 正 扩 容 之 前 检 测 是 否 能 扩 容 成 功 , 防 止 太 大 导 致 扩 容 失 败
3. 使 用 c o p y O f进 行 扩 容