初识ArrayList
一、简介:
ArrayList是 java 集合框架中比较常用的数据结构了。继承自 AbstractList,实现了 List 接口。底层基于数组实现容量大小动态变化。允许 null 的存在。同时还实现了 RandomAccess、Cloneable、Serializable 接口,所以ArrayList 是支持快速访问、复制、序列化的。
ArrayList底层数据结构是数组,查询快,增删慢,线程不安全,效率高,可以存储重复元素
二、常用方法:
add:添加元素
ArrayList<String> list = new ArrayList<>(); list.add("张三"); list.add("李四"); list.add("王五"); list.add("赵六"); System.out.println(list);
输出结果:
![]()
add(int index, String element):在此列表中的指定位置插入指定的元素。
//在此列表中的指定位置插入指定的元素。 list.add(2, "钱七");//在下标为2的位置添加元素
![]()
addAll(Collection<? extends E> c):按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。
//按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾。 ArrayList<String> newList = new ArrayList<>(); Collections.addAll(newList, "孙悟空", "猪八戒", "沙和尚"); list.addAll(newList);
输出结果为:
![]()
addAll(int index, Collection<? extends E> c):将指定集合中的所有元素插入到此列表中,从指定的位置开始。
ArrayList<String> newList2 = new ArrayList<>(); Collections.addAll(newList2, "如来", "唐僧", "观音"); list.addAll(2, newList2);//在下标为2的位置插入newList2集合
输出结果:
![]()
remove:删除该列表中指定位置的元素。
list.remove("钱七");//删除元素为"钱七"的元素
![]()
list.remove(6);//删除指定下标的元素
![]()
//从此列表中删除指定集合中包含的所有元素。
list.removeAll(newList2);
![]()
retainAll:仅保留此列表中包含在指定集合中的元素。
list.retainAll(newList1);
set:用指定的元素替换此列表中指定位置的元素。
list.set(1, "马保国");
![]()
size():返回此列表中的元素数。
System.out.println("size = " + list.size());
toArray():以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。
Object[] array = list.toArray(); System.out.println(Arrays.toString(array));
三、手撕ArrayList的底层结构
ArrayList的底层结构是一个Object类型的一维数组,继承了AbstractList类,并且实现了List接口, RandomAccess接口和 Cloneable接口。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ //默认初始容量。 private static final int DEFAULT_CAPACITY = 10; //没有元素的空数组(长度为0) private static final Object[] EMPTY_ELEMENTDATA = {}; //空内容的数组(长度为0) private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //容器(ArrayList集合中所有的元素都是存在这个一维数组里的) transient Object[] elementData;//new Object[10] //元素个数(指针) private int size; //数组最大容量 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //最大容量之所以是Integer的最大值-8,是因为ArrayList的底层就是一个以为数组,一维数组存储在堆内存中,会占用一定的内存空间,比如我们的头部信息,包括了其中的内存地址以及数组长度,数据类型等信息 //ArrayList的无参构造 public ArrayList() { //构造一个初始容量为10的空列表。 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } //ArrayList的有参构造 public ArrayList(int initialCapacity) { //验证初始化容量的合法性 if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } public boolean add(E e) { ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } //使用无参构造创建对象时,第一次添加元素就会进入的判断 private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//minCapacity = 10 } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; //有溢出意识的代码 -- 判断是否可以扩容(要扩容的长度必须大于原数组的长度) if (minCapacity - elementData.length > 0) grow(minCapacity); } private void grow(int minCapacity) { // 有溢出意识的代码 -- 计算扩容的容量 int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容机制为原数组长度的1.5倍 if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); elementData = Arrays.copyOf(elementData, newCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; } }
public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("张三"); list.add("李四");
总结:
- ArrayList的底层是Object类型的一位数组
- 在使用无参构造的时候,ArrayList会将数组赋值成没有长度的空数组
- 在使用有参构造的时候,如果参数大于0,则创建参数长度的数组,如果参数等于0会将数组赋值成没有长度的空数组,如果参数小于0就会报错
- ArrayList的底层有个变量规定初始化容量为10(DEFAULT_CAPACITY = 10),如果使用无参构造创建ArrayList对象,第一次添加元素的时候,会将底层的Object类型的一维数组初始化为10长度的数组
- ArrayList的扩容机制是1.5倍(int newCapacity = oldCapacity + (oldCapacity >> 1))
- ArrayList的最大容量为:Integer.MAX_VALUE-8