浅谈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的修改,影响迭代器遍历操作。

posted @ 2014-03-07 13:37  yyrookie  阅读(247)  评论(0编辑  收藏  举报