浅谈Java中的ArrayList类
ArrayList就是传说中的动态数组,就是数组的封装实现,它提供了动态的增加和减少元素,灵活的设置数组的大小等好处,主要实现了Collection,Iterable,RandomAccess(修饰接口,表明这个类可以随机访问)等。
ArrayList提供了3种构造方法:
1.可以构造一个指定容量大小的ArrayList对象
1 /** 2 * Constructs an empty list with the specified initial capacity. 3 * 4 * @param initialCapacity the initial capacity of the list 5 * @throws IllegalArgumentException if the specified initial capacity 6 * is negative 7 */ 8 public ArrayList(int initialCapacity) { 9 super(); 10 if (initialCapacity < 0) 11 throw new IllegalArgumentException("Illegal Capacity: "+ 12 initialCapacity); 13 this.elementData = new Object[initialCapacity]; 14 }
2.构造一个默认大小的ArrayList对象,
1 /** 2 * Constructs an empty list with an initial capacity of ten. 3 */ 4 public ArrayList() { 5 super(); 6 this.elementData = EMPTY_ELEMENTDATA; 7 }
/**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
* DEFAULT_CAPACITY when the first element is added.
*/
private transient Object[] elementData;
当第一次add的时候 如果elementData == EMPTY_ELEMENTDATA,将会最小扩充到DEFAULT_CAPACITY = 10容量的大小
3.构造一个包含某个Collection容器中所有对象的ArrayList对象
1 /** 2 * Constructs a list containing the elements of the specified 3 * collection, in the order they are returned by the collection's 4 * iterator. 5 * 6 * @param c the collection whose elements are to be placed into this list 7 * @throws NullPointerException if the specified collection is null 8 */ 9 public ArrayList(Collection<? extends E> c) { 10 elementData = c.toArray(); 11 size = elementData.length; 12 // c.toArray might (incorrectly) not return Object[] (see 6260652)
13 if (elementData.getClass() != Object[].class) 14 elementData = Arrays.copyOf(elementData, size, Object[].class); 15 }
注意
// c.toArray might (incorrectly) not return Object[] (see 6260652)
返回若不是Object[]将调用 Arrays.copyOf方法将其转为Object[],至于6260652应该是对于他们jdk的bug编号.
如下demo:
1 public class Test { 2 public static void main(String[] args) { 3 List<Object> l = new ArrayList<Object>(Arrays.asList("foo", "bar")); 4 Object[] obj; 5 obj = Arrays.asList("foo", "bar").toArray(); 6 // Arrays.asList("foo", "bar").toArray() produces String[], 7 System.out.println(obj.getClass().getName());//实际是String[]对象 8 obj = Arrays.copyOf(obj, obj.length, Object[].class);//转成Object[]对象 9 System.out.println(obj.getClass().getName()); 10 l.set(0, new Object()); // Causes ArrayStoreException 11 } 12 }
/** * Trims the capacity of this <tt>ArrayList</tt> instance to be the * list's current size. An application can use this operation to minimize * the storage of an <tt>ArrayList</tt> instance. */ public void trimToSize() { modCount++; if (size < elementData.length) { elementData = Arrays.copyOf(elementData, size); } }
此方法是为了修剪ArrayList的容量,并将modcount+1
1 private void grow(int minCapacity) { 2 // overflow-conscious code 3 int oldCapacity = elementData.length; 4 int newCapacity = oldCapacity + (oldCapacity >> 1); 5 if (newCapacity - minCapacity < 0) 6 newCapacity = minCapacity; 7 if (newCapacity - MAX_ARRAY_SIZE > 0) 8 newCapacity = hugeCapacity(minCapacity); 9 // minCapacity is usually close to size, so this is a win: 10 elementData = Arrays.copyOf(elementData, newCapacity); 11 }
ArrayList 一般情况下以1/2倍数为增量,进行增长
1 private static int hugeCapacity(int minCapacity) { 2 if (minCapacity < 0) // overflow 3 throw new OutOfMemoryError(); 4 return (minCapacity > MAX_ARRAY_SIZE) ? 5 Integer.MAX_VALUE : 6 MAX_ARRAY_SIZE; 7 }
这里用来判断容量是否内存越界,由这个方法可见ArrayList的最大容量为Integer.MAX_VALUE
1 public boolean contains(Object o) { 2 return indexOf(o) >= 0; 3 } 4 5 public int indexOf(Object o) { 6 if (o == null) { 7 for (int i = 0; i < size; i++) 8 if (elementData[i]==null) 9 return i; 10 } else { 11 for (int i = 0; i < size; i++) 12 if (o.equals(elementData[i])) 13 return i; 14 } 15 return -1; 16 }
这里可以看出ArrayList中可能存在null对象,并且需要我们重写equals方法,如果不重写equals方法,那么默认使用Object的equals
1 /** 2 * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The 3 * elements themselves are not copied.) 4 * 5 * @return a clone of this <tt>ArrayList</tt> instance 6 */ 7 public Object clone() { 8 try { 9 @SuppressWarnings("unchecked") 10 ArrayList<E> v = (ArrayList<E>) super.clone(); 11 v.elementData = Arrays.copyOf(elementData, size); 12 v.modCount = 0; 13 return v; 14 } catch (CloneNotSupportedException e) { 15 // this shouldn't happen, since we are Cloneable 16 throw new InternalError(); 17 } 18 }
clone()方法是重写Object对象的clone() 实现了对对象的拷贝,不过ArrayList clone是对ArrayList对象的浅拷贝。
如下demo:
1 public class Test { 2 public static void main(String[] args) { 3 ArrayList<StringBuffer> array1 = new ArrayList<StringBuffer>(); 4 StringBuffer str = new StringBuffer("first"); 5 array1.add(str); 6 ArrayList<StringBuffer> array2 = (ArrayList<StringBuffer>) array1.clone(); 7 System.out.println(array1); 8 System.out.println(array2); 9 10 str.append(" second"); 11 12 System.out.println(array1); 13 System.out.println(array2); 14 } 15 // [first] 16 // [first] 17 // [first second] 18 // [first second] 19 }
注意:ArrayList中频繁出现对modCount字段的操作,是以为迭代器遍历正常。在AbstractList中有如下代码实现:
1 final void checkForComodification() { 2 if (modCount != expectedModCount) 3 throw new ConcurrentModificationException(); 4 }
防止多线程对ArrayList的修改,影响迭代器遍历操作。