List接口中,重要的两个实现是ArrayList和LinkedList,其中ArrayList又比LinkedList经常使用。这是由于ArrayList的读取性能远远高于LinkedList。本篇博文将介绍ArrayList,稍后介绍LinkedList及其二者的区别。java
Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List interface,this class provides methods to manipulate the size of the array that is used internally to store the list.
ArrayList是实现了List接口的、大小可变的数组队列。可以实现全部List接口的可选操做,并容许包括 null 在内的全部元素。除了实现 List 接口外,此类还提供一些方法来存储列表的数组的大小。(此类大体上等同于 Vector 类,除了此类是不一样步的。)--JDK API翻译(可能不是很精确,请谅解)算法
从API的定义中能够看出,ArrayList是一个数组队列,至关于动态数组。与数组相比,可以动态增加。api
java.util 类 ArrayList<E> java.lang.Object - java.util.AbstractCollection<E> - java.util.AbstractList<E> - java.util.ArrayList<E> 全部已实现的接口: Serializable, Cloneable, Iterable<E>, Collection<E>, List<E>, RandomAccess
ArrayList继承了AbstractList,实现了List,它是一个数组队列,提供了相关的增、改、删数组
查等功能。安全
ArrayList实现了RandomAccess接口,提供了随机访问功能。RandomAccess是List 实现所使用的标记接口,用来代表其支持快速(一般是固定时间)随机访问。此接口的主要目的是容许通常的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能。(来自JDk API翻译)数据结构
ArrayList实现了Cloneable接口,提供了克隆功能多线程
ArrayList实现了java.io.Serializable借口,这意味着ArrayList支持序列化。并发
注意:ArrayList是非线程安全的!因此,建议在多线程程序中避免使用ArrayList,可使用Vector或者CopyOnWriteArrayList。(这两个类的用法及其实现,在稍后的博文中将被介绍)app
package java.util; public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { //序列版本号 private static final long serialVersionUID = 8683452581122892189L; /** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. * 数组缓冲区中的数组的元素存储,即保存ArrayList中数据的数组 */ private transient Object[] elementData; /** * The size of the ArrayList (the number of elements it contains). * ArrayList中实际数据的数量 * @serial */ private int size; }
从源码中看到ArrayList有2个重要对象dom
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { /** * Constructs an empty list with the specified initial capacity. * * 构造一个具备指定初始容量的空列表。 */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); //新建一个数组,大小为入参值 this.elementData = new Object[initialCapacity]; } /** * Constructs an empty list with an initial capacity of ten. * ArrayList的无参构造器, 构造一个初始容量为 10 的空列表 */ public ArrayList() { this(10); } /** * Constructs a list containing the elements of the specified * collection, in the order they are returned by the collection's * iterator. * * 构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。 */ public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) //Arrays.copyOf方法:数组复制 elementData = Arrays.copyOf(elementData, size, Object[].class); } }
当ArrayList容量不足以容纳所有元素时,ArrayList会从新设置容量:新的容量 = (原始容量 X 3) / 2 + 1。再次说明在添加大量元素前,应用程序应该使用 ensureCapacity 操做来增长 ArrayList 实例的容量。以减小递增式再分配的数量。
/** * Increases the capacity of this <tt>ArrayList</tt> instance, if * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * 增长此 ArrayList 实例的容量,以确保它至少可以容纳最小容量参数所指定的元素数。 */ public void ensureCapacity(int minCapacity) { //将修改统计计数 +1 modCount++; int oldCapacity = elementData.length; //若是传入最小容量大于原来数组的长度,就增长arrayList容量 //新的容量 = (原始容量 * 3)/2 + 1 if (minCapacity > oldCapacity) { Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); } }
将此 ArrayList 实例的容量调整为列表的当前大小。应用程序可使用此操做来最小化 ArrayList 实例的存储量。
/** * Trims the capacity of this ArrayList instance to be the list's current size. * 将此 ArrayList 实例的容量调整为列表的当前大小,也即将当前容量值设置为实际元素个数 */ public void trimToSize() { modCount++; int oldCapacity = elementData.length; if (size < oldCapacity) { elementData = Arrays.copyOf(elementData, size); } }
将指定的元素添加到此列表的尾部。在调整数组大小以前要判断是否须要调整arrayList容量
/** * Appends the specified element to the end of this list. * * 添加元素e */ public boolean add(E e) { //肯定ArrayList容量大小 ensureCapacity(size + 1); // Increments modCount!! //添加e到ArrayList尾部 elementData[size++] = e; return true; }
/** * Returns true if this list contains the specified element. * 返回ArrayList是否包含Object(o) */ public boolean contains(Object o) { return indexOf(o) >= 0; } /** * Returns the index of the first occurrence of the specified element * in this list, or -1 if this list does not contain the element. * 正向查找,返回元素的索引值,若是元素不存在集合中,就返回-1 */ public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; }
package java.util; public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { // 正向查找,返回元素的索引值 public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size; i++) if (elementData[i]==null) return i; } else { for (int i = 0; i < size; i++) if (o.equals(elementData[i])) return i; } return -1; } // 反向查找,返回元素的索引值 public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } // 反向查找(从数组末尾向开始查找),返回元素(o)的索引值 public int lastIndexOf(Object o) { if (o == null) { for (int i = size-1; i >= 0; i--) if (elementData[i]==null) return i; } else { for (int i = size-1; i >= 0; i--) if (o.equals(elementData[i])) return i; } return -1; } // 返回ArrayList的Object数组 public Object[] toArray() { return Arrays.copyOf(elementData, size); } // 返回ArrayList的模板数组。所谓模板数组,便可以将T设为任意的数据类型 public <T> T[] toArray(T[] a) { // 若数组a的大小 < ArrayList的元素个数; // 则新建一个T[]数组,数组大小是“ArrayList的元素个数”,并将“ArrayList”所有拷贝到新数组中 if (a.length < size) return (T[]) Arrays.copyOf(elementData, size, a.getClass()); // 若数组a的大小 >= ArrayList的元素个数; // 则将ArrayList的所有元素都拷贝到数组a中。 System.arraycopy(elementData, 0, a, 0, size); if (a.length > size) a[size] = null; return a; } // 设置index位置的值为element public E set(int index, E element) { RangeCheck(index); E oldValue = (E) elementData[index]; elementData[index] = element; return oldValue; } // 将e添加到ArrayList的指定位置 public void add(int index, E element) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); ensureCapacity(size+1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } // 删除ArrayList指定位置的元素 public E remove(int index) { RangeCheck(index); modCount++; E oldValue = (E) elementData[index]; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); elementData[--size] = null; // Let gc do its work return oldValue; } // 删除ArrayList的指定元素 public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } // 快速删除第index个元素 private void fastRemove(int index) { modCount++; int numMoved = size - index - 1; // 从"index+1"开始,用后面的元素替换前面的元素。 if (numMoved > 0) System.arraycopy(elementData, index+1, elementData, index, numMoved); // 将最后一个元素设为null elementData[--size] = null; // Let gc do its work } // 删除元素 public boolean remove(Object o) { if (o == null) { for (int index = 0; index < size; index++) if (elementData[index] == null) { fastRemove(index); return true; } } else { // 便利ArrayList,找到“元素o”,则删除,并返回true。 for (int index = 0; index < size; index++) if (o.equals(elementData[index])) { fastRemove(index); return true; } } return false; } // 清空ArrayList,将所有的元素设为null public void clear() { modCount++; for (int i = 0; i < size; i++) elementData[i] = null; size = 0; } // 将集合c追加到ArrayList中 public boolean addAll(Collection<? extends E> c) { Object[] a = c.toArray(); int numNew = a.length; ensureCapacity(size + numNew); // Increments modCount System.arraycopy(a, 0, elementData, size, numNew); size += numNew; return numNew != 0; } // 从index位置开始,将集合c添加到ArrayList public boolean addAll(int index, Collection<? extends E> c) { if (index > size || index < 0) throw new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size); Object[] a = c.toArray(); int numNew = a.length; ensureCapacity(size + numNew); // Increments modCount int numMoved = size - index; if (numMoved > 0) System.arraycopy(elementData, index, elementData, index + numNew, numMoved); System.arraycopy(a, 0, elementData, index, numNew); size += numNew; return numNew != 0; } // 删除fromIndex到toIndex之间的所有元素。 protected void removeRange(int fromIndex, int toIndex) { modCount++; int numMoved = size - toIndex; System.arraycopy(elementData, toIndex, elementData, fromIndex, numMoved); // Let gc do its work int newSize = size - (toIndex-fromIndex); while (size != newSize) elementData[--size] = null; } // 克隆函数 public Object clone() { try { ArrayList<E> v = (ArrayList<E>) super.clone(); // 将当前ArrayList的所有元素拷贝到v中 v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } } }
集合操做中最多见的就是遍历操做了,ArrayList支持3种遍历方式:迭代器遍历、随机访问和for循环|(foreach循环)
Integer value = null; Iterator iter = list.iterator(); while (iter.hasNext()) { value = (Integer)iter.next(); }
Integer value = null; int size = list.size(); for (int i=0; i<size; i++) { value = (Integer)list.get(i); }
Integer value = null; for (Integer integ:list) { value = integ; }
package com.my.mobile; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class TestArrayList { public static void main(String[] args) { TestArrayList t = new TestArrayList(); List<Data> initArrayList = t.initArrayList(100000); testiterator(initArrayList); testRandomAccess(initArrayList); testforeach(initArrayList); } /** * 测试foreach循环遍历ArrayList性能 * @param initArrayList * */ private static void testforeach(List<Data> initArrayList) { // TODO Auto-generated method stub long starttime = System.currentTimeMillis(); for (Data data : initArrayList) { // System.out.println(data.toString()); } System.out.println("foreach遍历完毕,耗时["+(System.currentTimeMillis() - starttime)+"]ms"); } private static void testRandomAccess(List<Data> initArrayList) { // TODO Auto-generated method stub long starttime = System.currentTimeMillis(); for(int i = 0;i<initArrayList.size();i++){ Data data = initArrayList.get(i); // System.out.println(data.toString()); } System.out.println("randomAccess遍历完毕,耗时["+(System.currentTimeMillis() - starttime)+"]ms"); } private static void testiterator(List<Data> initArrayList) { // TODO Auto-generated method stub long starttime = System.currentTimeMillis(); for(Iterator<Data> iter = initArrayList.iterator();iter.hasNext();){ Data data = iter.next(); // System.out.println(data.toString()); } System.out.println("iterator遍历完毕,耗时["+(System.currentTimeMillis() - starttime)+"]ms"); } private List<Data> initArrayList(int listSize){ Data data = new Data(); List<Data> arrayList = new ArrayList<Data>(); for(int i = 0;i<listSize;i++){ try { TestArrayList.Data data_clone = data.clone(); data_clone.setId(i+""); data_clone.setName("我是第"+i+"个酷酷的酷"); data_clone.setUser("kucs"); arrayList.add(data_clone); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return arrayList; } class Data implements Cloneable{ private String id; private String name; private String user; public Data() { super(); // TODO Auto-generated constructor stub } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } @Override public String toString() { return "Data [id=" + id + ", name=" + name + ", user=" + user + "]"; } @Override protected Data clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return (Data)super.clone(); } } }
运行结果:
iterator遍历完毕,耗时[34]ms randomAccess遍历完毕,耗时[12]ms foreach遍历完毕,耗时[14]ms
经此实验,遍历ArrayList时,使用随机访问,遍历比较快。