package course.collection; import java.util.ArrayList; /** * @author WanJl * @version 1.0 * @title Demo02 * @description * @create 2026/7/29 */ public class Demo02 { /* 我们一般把集合 称为集合框架,因为集合是把一些底层数据结构进行了封装。 比如单列集合中的List List直译就是列表,也就是对应数据结构中的 线性表结构 线性表结构大致可以分为四种: 栈结构: 先进后出,加入元素,称为 入栈、压栈。 移除元素,称为出栈、弹栈。 队列结构: 先进先出 数组结构: 是连续的数据存储,查询的时候可以通过索引快速定位, 增删的时候,需要修改前后进行移动。所以增删慢,查询快。 链表结构: 是不连续的存储,不需要在内存中开辟连续的存储空间, 只需要从头结点开始,每个节点都有一个执行下一个节点的指针(地址)。 随机查询的时候,需要从第1个结点开始依次向后查找,查询速度慢。 增删的时候,只需要改变临近结点的指针,就可以。所以增删速度快。 List的实现类对应的数据结构: ArrayList:数组 LinkedList:队列、栈、链表 ArrayList: 本质是一个长度可变的数组,底层使用的是数组。 ArrayList 里面可以存储 null 和Vector差不多,但是不是线程同步的。性能更高一些。 ArrayList有一个参数 Capacity,容量会随着元素的增加而增加,并且会进行扩容。 ArrayList的默认初始容量为10 private static final int DEFAULT_CAPACITY = 10; 内部还有一个空的Object类型的数组 private static final Object[] EMPTY_ELEMENTDATA = {}; 还有一个默认容量的空数组 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; ArrayList中维护的底层数组就是elementData。 空数组没有任何元素插入的时候,就使用的数组容量是DEFAULTCAPACITY_EMPTY_ELEMENTDATA 但是,如果插入了一个元素,立马把elementData的容量扩容到DEFAULT_CAPACITY(也就是10) transient Object[] elementData; elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 只要增加了一个元素,就变成了: elementData=new Object[DEFAULT_CAPACITY] ArrayList有一个属性,是元素的个数,不是数组长度。 而是数组中存储有效元素的个数。 private int size; ArrayList中有一个返回元素个数的方法:size(),返回的就是size属性。 判断是否为空isEmpty()返回的就是size是否等于0 ArrayList有三个构造方法: ArrayList(int initialCapacity) 创建一个ArrayList集合对象,指定初始容量为initialCapacity ArrayList() 创建一个ArrayList集合对象,指定初始容量为0: elementData=DEFAULTCAPACITY_EMPTY_ELEMENTDATA; 把维护的elementData数组,设置为空数组。 ArrayList(Collection c) 创建一个ArrayList集合对象,传入的是Collection接口的实现类对象。 其实就是把另一个集合对象的元素加入到新建的ArrayList结合对象中 trimToSize():缩减容量为集合有效元素个数 elementData = (size == 0)? EMPTY_ELEMENTDATA: Arrays.copyOf(elementData, size); elementData =EMPTY_ELEMENTDATA elementData =Arrays.copyOf(elementData, size); ensureCapacity(int minCapacity) 确保容量-自动扩容的前提 每当向数组elementData添加元素的时候,都要去先检查一遍添加后的元素个数是否会超过当前的数组的长度。 如果超过,就要扩容。数组扩容是通过ensureCapacity()来实现的,确保容量足够。 在实际添加大量元素之前,我们可以使用ensureCapacity()来手动增加ArrayList的容量。 这个方法是使用public修饰的,就是我们如果想要添加大量元素,就可以调用这个方法,手动扩容。 直接扩容到期望最小容量minCapacity 只有满足下面两个条件,才会进行扩容 minCapacity > elementData.length 期望的最小容量要大于当前维护的数组长度 !(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA && minCapacity <= DEFAULT_CAPACITY) elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA 如果是空数组 minCapacity <= DEFAULT_CAPACITY 期望的最小容量,如果小于等于默认容量 两个条件同时满足后取反。也就是,elementData既不能是空数组,也不能是期望的最小容量小于等于默认容量。才会进行扩容 Object[] grow(int minCapacity) 扩容 oldCapacity 旧的容量 minCapacity - oldCapacity 最小要增加的容量 oldCapacity >> 1 最好增加的容量 就是 旧的容量除以2 ArraysSupport.newLength(oldCapacity,minCapacity - oldCapacity, oldCapacity >> 1 ); 比如 旧容量 10 最小 10 最好增加的容量 10/2 5 10+5 =15 刚好是原来的1.5倍 ArrayList每次扩容的时候,都是原来容量的1.5倍。 ArrayList常用的方法: 创建集合对象: ArrayList list=new ArrayList<>(); list.add(对象); //添加元素到集合 list.add(索引值,对象);//添加元素到集合的指定位置 list.isEmpty(); //判断集合是否为空 list.size();//获取集合长度 list.toArray();//把集合转换为数组 list.get(索引值); //获取指定索引位置的元素 list.getFirst();//获取集合第一个元素 list.getLast();//获取集合最后一个元素 list.indexOf(对象);查询集合中这个元素首次出现的索引值,没有就返回-1 list.remove(对象);// 移除集合中指定的元素 list.clear(); 清空集合 */ public static void main(String[] args) { ArrayList list01=new ArrayList<>(); //创建一个默认容量为10集合 ArrayList list02=new ArrayList<>(20);//创建一个初始容量为20集合 ArrayList list03=new ArrayList<>(list02);//创建一个集合,以另一个集合为参数,加入到当前集合。 System.out.println(list01.size()); System.out.println(list02.size()); System.out.println(list03.size()); System.out.println(20<<1); System.out.println(20>>1); } }