ArrayList的底层实现(常用方法)

    技术2022-07-10  128

    本文对ArrayList从初始化到使用进行一个详细介绍: ArrayList可以简单的把它当做一个存放数据的容器,既然是存放数据。那必然离不开增删改查几个操作。

     

    1.【初始化】,在使用之前,肯定得要先new出来一个数组对象

    JDK1.8中ArrayList()初始化后的底层数组长度为0,且在添加第一个元素时,底层数据长度变为10,之后扩容按原来的1.5倍进行扩容。

    2.【增】添加元素,有了ArrayList集合之后,可以往里面添加元素

    上图从上往下 1. 直接从尾部追加单个数据 2.在指定的index处添加数据(策略:从最尾部开始到index位置,依次往后复制一位,然后将新增的元素放入index处) 图解2: 3.类似于1,只是把单个元素变为一个集合 4.类似于2,只是把单个元素变为一个集合

    至此我们可以得到arraylist的一个特点:添加元素效率低(因为需要将后续的元素依次后移一位,再加入进去)

    上文都提到了,第一次添加元素之后,容量为10,那么多次添加元素之后,自然会装满集合,装满之后。就会涉及到扩容扩容策略:新建一个集合,大小为之前容量的1.5倍  10->15    15->22(保留整数位)  将原集合中的元素拷贝到新集合中

    3.【查】获取元素

    获取元素的时候,根据下标的index,直接就能得到元素。 所以arraylist的另一个特点:查询效率高

    4.【删】删除元素

    上图从上往下 1.删除指定下标的元素,直接从最后一个元素到index的后一位元素,依次往前复制覆盖。然后将末尾元素置空 2.删除指定元素,从0到size位置循环遍历,判断是否找到该元素,找到元素之后,记录元素下标,然后根据下标移除该元素(核心同1,都是调用System.arraycopy 方法,进行覆盖复制,然后移除最尾部元素) 3.删除列表中包含C的所有元素 4.删除列表中给定谓词的所有元素   (34用的比较少,没有深入研究) 5.清空集合,循环集合从0到index进行置空处理,然后将size修改为0

    删除因为涉及元素的复制移动,所以删除效率低

    5.【改】修改元素

    1.set(index,element):直接将index位置上的元素更换为element 2.retainAll( Collection<?> c ):仅仅保留列表中和C相同的元素,相当于&运算 3.subList( int from , int to ):返回从from到to之间的列表(左闭右开),注:返回值类型为List

    #. 总结

    底层数据结构采用数组线程不安全增加,删除元素效率低查询效率高

    #.【附代码,建议结合源码阅读理解】

    package list; import java.util.ArrayList; import java.util.List; public class MyArrayList { /** * 打印集合,用于观看结果 * @param <E> */ public static <E> void printList(String msg,List<E> l1){ System.out.print(msg+ ":"); for (E i : l1){ System.out.print(i+" "); } System.out.println(); } public static void main(String[] args) { //ArrayList()初始化后的底层数组长度为0,添加第一个元素时,长度变为10 ArrayList<Integer> list1 = new ArrayList<Integer>(); /*【增】 * add(index)方法:在集合尾部直接追加元素 * 补充: * list1.addAll(c) 类似上述方法,只是把单个元素变为集合 */ list1.add(1); list1.add(2); list1.add(3); printList("第一次add元素",list1); /*【增】 * add(index,element)方法:在集合的index处添加元素 * 原理: * 1.从集合最后一位到index位(size->index)依次往右复制一位 * 2.将element放进index位置,完成添加 * 补充: * list1.addAll(index,c) 类似上述方法,只是把单个元素变为集合 */ /**【扩容】 * 第一次添加元素之后,容量为10, * 多次添加元素之后,自然会装满集合,装满之后。就会涉及到扩容 * 扩容策略: * 1.新建一个集合,大小为之前容量的1.5倍 10->15 15->22(奇数扩容时保留整数位) * 2.将原集合中的元素拷贝到新集合中 */ list1.add(0,99); printList("在0下标处添加元素99后",list1); /* * 【删】 * remove(index)方法:删除指定index处的元素 * 原理: * 1.从最后一个元素到index的后一位元素,依次往前复制覆盖。 * 2.然后将末尾元素置空 */ list1.remove(0); //这里是删除0下标位置处元素 printList("删除0下标处的元素后",list1); /* * 【删】 * remove(o)方法:删除值为o的元素 * 原理: * 1.循环集合,找到值为o的元素的下标,记录index值 * 2.从最后一个元素到index的后一位元素,依次往前复制覆盖。 * 3.然后将末尾元素置空 * 补充: * 与上面的remove方法核心代码相同 * 都是System.arraycopy(elementData,index+1,elementData,index,numMoved) */ list1.remove((Integer)2); //这里是删除值为2的元素(因为我的集合是integer类型,不强转的话会被认为是删除index位置的元素) printList("删除值2后",list1); /* * 【改】 * list1.set(index, element),直接将index位置的元素更改为element */ list1.set(0, 999); printList("将0下标处的元素改为999后",list1); } }

     

     

     

    Processed: 0.015, SQL: 12