在我们之前的学习中,我们已经接触到了数组,在Java里,使用数组解决问题是十分高效的;但是,我们知道,数组一但被初始化时候,那么他的长度就不能再改变了;即数组是静态的。
我们在数据结构这里引进可一种新型的结构——ArrayList。ArrayList就是传说中的动态数组,我们可以把它看作是Array的复杂版本,在我们使用的过程中,他可以为我们带来更好的使用:比如说:
- 我们可以动态的增加、减少元素;
- 我们可以灵活的设置数组的大小;
- 实现了Collection和list接口在使用时更简单。
ArrayList的使用
1. ArrayList的构造
| ArrayList() | 无参构造 |
| ArrayList(Collection<? extends E> c) | 利用其他 Collection 构建 ArrayList |
| ArrayList(int initialCapacity) | 指定顺序表初始容量 |
public static void main(String[] args) {
// 1.无构造参数
List<Integer> list = new ArrayList<>();
// 2.构造一个指定顺序表初始容量
List<Integer> list1 = new ArrayList<>(10);
list1.add(1);
list1.add(2);
list1.add(3);
// 3.list2,list3构造好后,与list2一致
ArrayList<Integer> list2 = new ArrayList<>(list1);
List<Integer> list3 = new ArrayList<>(list1);
// 4.注意:不要忘记<>里的类型
}
2. ArrayList常见的方法
| 方法 | 解释 |
| boolean add(E e) | 尾插 e |
| void add(int index, E element) | 将 e 插入到 index 位置 |
| boolean addAll(Collection<? extends E> c) | 尾插 c 中的元素 |
| E remove(int index) | 删除 index 位置元素 |
| boolean remove(Object o) | 删除遇到的第一个 o |
| E get(int index) | 获取下标 index 位置元素 |
| E set(int index, E element) | 将下标 index 位置元素设置为 element |
| void clear() | 清空 |
| boolean contains(Object o) | 判断 o 是否在线性表中 |
| int indexOf(Object o) | 返回第一个 o 所在下标 |
| int lastIndexOf(Object o) | 返回最后一个 o 的下标 |
| List<E> subList(int fromIndex, int toIndex) |
截取部分 list |
具体的使用过程:------》
public static void main(String[] args) {
// 1.无构造参数
//List<Integer> list = new ArrayList<>();
// 2.构造一个指定顺序表初始容量
List<Integer> list1 = new ArrayList<>(10);
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);
list1.add(6);
// 3.list2,list3构造好后,与list2一致
//ArrayList<Integer> list2 = new ArrayList<>(list1);
//List<Integer> list3 = new ArrayList<>(list1);
// 4.注意:不要忘记<>里的类型
System.out.println("第一次add "+list1);
System.out.println("size "+list1.size());
System.out.println("1位置元素 "+list1.get(1));
list1.add(1,9);
System.out.println("修改后1位置 "+list1.get(1));
System.out.println("===========================================");
list1.remove(1);
System.out.println(list1);
System.out.println(list1.contains(3));
list1.add(1);
System.out.println(list1.indexOf(1));
System.out.println(list1.lastIndexOf(1));
List<Integer> list2 = list1.subList(1,4);
System.out.println(list2);
}

3. ArrayList的遍历
有三种遍历方式:
- for循环;
// 1.遍历 for (int i = 0; i < list1.size(); i++) { System.out.print(list1.get(i) + " "); } System.out.println(); - foreach;
// 2.foreach for (Integer a:list1) { System.out.print(a+ " "); } System.out.println(); - 使用迭代器;
// 3.使用迭代器 Iterator<Integer> interator = list1.iterator(); while (interator.hasNext()) { System.out.print(interator.next()+" "); } System.out.println();
4. 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);
} r
eturn 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;
// 如果需要扩容大小超过MAX_ARRAY_SIZE,重新计算容量大小
if (newCapacity - MAX_ARRAY_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();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}
总结:
1. 检测是否真正需要扩容,如果是调用grow准备扩容
2. 预估需要库容的大小
- 初步预估按照1.5倍大小扩容
- 如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容
- 真正扩容之前检测是否能扩容成功,防止太大导致扩容失败
3. 使用copyOf进行扩容
ArrayList是Java中的动态数组,提供比静态数组更灵活的增删改操作。它实现了Collection和List接口,方便使用。本文将探讨ArrayList的构造、常用方法、遍历方式(包括for循环、foreach和迭代器)以及其扩容机制。在扩容时,ArrayList会根据需要按1.5倍或用户指定大小进行扩展,并确保扩容操作成功。

1245

被折叠的 条评论
为什么被折叠?



