Java基础-ArrayList
一. 类说明
ArrayList是List接口的可调整大小的数组的实现。实现了所有可选的list操作,并允许元素为null。除了实现List接口之外,此类还提供了一些方法来操作内部用于存储列表的数组大小。这个类大致等同于Vector,只是它不同步。
这些操作siz, isEmpty, get, set, iterator和listIterator运行在“恒定”时间。这个add操作运行在“amortized constant time”(非恒定时间),因此,新增一个元素需要O(n)时间。所有的操作都是在线性时间运行的(粗略地说)。与LinkList相比,常量因子较低。
每一个ArrayList实例都有容量。容量事一个数组用来存储元素的大小在列表中。他总是至少和列表一样大小。当元素添加到ArrayList,他的容量会自动增长。除了新增元素具有一个固定的摊余时间成本这一个事实外,增长策略的细节没有被指定。
应用程序可以使用增加ArrayList实例的容量,在对他进行添加大量元素之前,这样可以减少增量重新分配的数量。
请注意,此实现不是同步的。如果多个线程同时访问一个ArrayList实例,并且至少有一个线程在结构上修改了该列表,那么他必须在外部同步。(结构修改是指添加或者删除一个多个元素,或者显示调整后备数组大小的任何操作)这通常是通过在一些自然封装列表的对象上进行同步来实现的。如果不存在这样的对象,则应该使用该方法对list进行包装,如下:
List list = Collections.synchronizedList(new ArrayList(...));
快速失败(fail-fast)
如果在迭代器创建后的任何时候去列表进行结构上的修改(除了通过迭代器使用自己的remove()或者add()外),该类的返回的迭代器和方法将快速失败,迭代器将抛出一个ConcurrentModificationException。因此,在并发修改的情况下,迭代器会迅速而彻底地失败,而不是在将来某个不确定的时间冒着任意不确定的风险。
请注意,迭代器的fail-fast的行为得不到保证。一般来说,在存在不同步的并发修改时,不可能做出任何硬保证,会尽最大努力抛出ConcurrentModificationException。因此编写一个依赖于这个异常来保证正确性的程序是错误的,这个只能用来检测bug。
二. 常见的方法
public static void main(String[] args){ ArrayList<Integer> arrayList = new ArrayList<>(); initList(arrayList); System.out.println("数组:" + arrayList.toString()); System.out.println("arrayList.get(0):" + arrayList.get(0)); System.out.println("size:" + arrayList.size());//元素的个数 System.out.println("isEmpty:" + arrayList.isEmpty()); System.out.println("是否包含9:" + arrayList.contains(9)); System.out.println("匹配查找的第一个元素值是9的索引:" + arrayList.indexOf(9)); System.out.println("匹配查找的最后个元素值是9的索引:" + arrayList.lastIndexOf(9)); System.out.println(Arrays.toString(arrayList.toArray(new Integer[0])));//将list转换为数组 arrayList.ensureCapacity(12); arrayList.add(11);//modeCount+1,检测是否需要扩容 System.out.println("数组新增元素:" + arrayList.toString()); arrayList.remove(2); System.out.println("数组删除元素:" + arrayList.toString()); arrayList.clear(); System.out.println("数组清空元素:" + arrayList.toString()); initList(arrayList);//size和capacity的概念不一样,size是元素的数量,capacity是底层数组的大小, ArrayList<Integer> arrayList2 = new ArrayList<>(); arrayList2.add(2);arrayList.add(111); arrayList.addAll(arrayList2); System.out.println("数组A添加数组B:" + arrayList.toString()); arrayList.removeAll(arrayList2); System.out.println("数组A移除数组B的元素:" + arrayList.toString()); arrayList.add(1);arrayList.add(2);arrayList.add(5); arrayList.retainAll(arrayList2);//交集 System.out.println("数组A与数组B的交集:" + arrayList.toString()); initList(arrayList); Iterator<Integer> iterator = arrayList.iterator(); iterator.forEachRemaining(x -> System.out.println("迭代剩余的元素forEachRemaining:" + x)); List<Integer> arrayList3 = arrayList.subList(0,2);//截取 System.out.println("arrayList截取:" + arrayList3.toString()); arrayList3.sort(Integer::compareTo); System.out.println("排序后:" + arrayList3.toString()); }
输出
数组:[1, 2, 10, 9, 8, 9] arrayList.get(0):1 size:6 isEmpty:false 是否包含9:true 匹配查找的第一个元素值是9的索引:3 匹配查找的最后个元素值是9的索引:5 [1, 2, 10, 9, 8, 9] 数组新增元素:[1, 2, 10, 9, 8, 9, 11] 数组删除元素:[1, 2, 9, 8, 9, 11] 数组清空元素:[] 数组A添加数组B:[1, 2, 10, 9, 8, 9, 111, 2] 数组A移除数组B的元素:[1, 10, 9, 8, 9, 111] 数组A与数组B的交集:[2] 迭代剩余的元素forEachRemaining:2 迭代剩余的元素forEachRemaining:1 迭代剩余的元素forEachRemaining:2 迭代剩余的元素forEachRemaining:10 迭代剩余的元素forEachRemaining:9 迭代剩余的元素forEachRemaining:8 迭代剩余的元素forEachRemaining:9 arrayList截取:[2, 1] 排序后:[1, 2] Process finished with exit code 0
三. 几种遍历的方法一览
public static void forDemo(ArrayList<Integer> list){ for (int i = 0; i < list.size(); i++){//普通for循环 //数组是在存储在连续的内存空间的有序的序列 System.out.println(i); } } public static void enhanceForDemo(ArrayList<Integer> list){ for(Integer i : list){//增强for循环,内部使用迭代器 System.out.println(i); } } public static void foreach(ArrayList<Integer> list){ //内部也是使用普通for循环的 list.forEach(integer -> System.out.println(integer)); }
增强for循环使用迭代器,可看编译后文件
public static void enhanceForDemo(ArrayList<Integer> list) { Iterator var1 = list.iterator(); while(var1.hasNext()) { Integer i = (Integer)var1.next(); System.out.println(i); } }
foreach内部实现代码
@Override public void forEach(Consumer<? super E> action) { Objects.requireNonNull(action); final int expectedModCount = modCount; @SuppressWarnings("unchecked") final E[] elementData = (E[]) this.elementData; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { action.accept(elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } }