本文对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);
}
}