src/share/classes/java/util/ArrayList.java

Print this page
rev 6816 : 80111200: (coll) Optimize empty HashMap and ArrayList
Reviewed-by: mduigou
Contributed-by: Sergey Linetskiy <sergey.linetskiy@oracle.com>, John Rose <john.rose@oracle.com>, Mike Duigou <mike.duigou@oracle.com>

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -103,10 +103,15 @@
         implements List<E>, RandomAccess, Cloneable, java.io.Serializable
 {
     private static final long serialVersionUID = 8683452581122892189L;
 
     /**
+     * Shared empty array instance used for empty instances.
+     */
+    private static final Object EMPTY_ELEMENTDATA[] = new Object[0];
+
+    /**
      * The array buffer into which the elements of the ArrayList are stored.
      * The capacity of the ArrayList is the length of this array buffer.
      */
     private transient Object[] elementData;
 

@@ -134,11 +139,12 @@
 
     /**
      * Constructs an empty list with an initial capacity of ten.
      */
     public ArrayList() {
-        this(10);
+        super();
+        this.elementData = EMPTY_ELEMENTDATA;
     }
 
     /**
      * Constructs a list containing the elements of the specified
      * collection, in the order they are returned by the collection's

@@ -160,12 +166,11 @@
      * list's current size.  An application can use this operation to minimize
      * the storage of an <tt>ArrayList</tt> instance.
      */
     public void trimToSize() {
         modCount++;
-        int oldCapacity = elementData.length;
-        if (size < oldCapacity) {
+        if (size < elementData.length) {
             elementData = Arrays.copyOf(elementData, size);
         }
     }
 
     /**

@@ -175,15 +180,24 @@
      *
      * @param   minCapacity   the desired minimum capacity
      */
     public void ensureCapacity(int minCapacity) {
         if (minCapacity > 0)
-            ensureCapacityInternal(minCapacity);
+            ensureExplicitCapacity(minCapacity);
     }
 
     private void ensureCapacityInternal(int minCapacity) {
+        if(elementData == EMPTY_ELEMENTDATA) {
+            minCapacity = Math.max(10, minCapacity);
+        }
+
+        ensureExplicitCapacity(minCapacity);
+    }
+
+    private void ensureExplicitCapacity(int minCapacity) {
         modCount++;
+
         // overflow-conscious code
         if (minCapacity - elementData.length > 0)
             grow(minCapacity);
     }
 

@@ -504,12 +518,11 @@
      */
     public void clear() {
         modCount++;
 
         // Let gc do its work
-        for (int i = 0; i < size; i++)
-            elementData[i] = null;
+        Arrays.fill(elementData, null);
 
         size = 0;
     }
 
     /**

@@ -586,12 +599,12 @@
         System.arraycopy(elementData, toIndex, elementData, fromIndex,
                          numMoved);
 
         // Let gc do its work
         int newSize = size - (toIndex-fromIndex);
-        while (size != newSize)
-            elementData[--size] = null;
+        Arrays.fill(elementData, newSize, size, null);
+        size = newSize;
     }
 
     /**
      * Checks if the given index is in range.  If not, throws an appropriate
      * runtime exception.  This method does *not* check if the index is

@@ -675,12 +688,12 @@
                                  elementData, w,
                                  size - r);
                 w += size - r;
             }
             if (w != size) {
-                for (int i = w; i < size; i++)
-                    elementData[i] = null;
+                // Let gc do its work
+                Arrays.fill(elementData, w, size, null);
                 modCount += size - w;
                 size = w;
                 modified = true;
             }
         }

@@ -700,20 +713,19 @@
         // Write out element count, and any hidden stuff
         int expectedModCount = modCount;
         s.defaultWriteObject();
 
         // Write out array length
-        s.writeInt(elementData.length);
+        s.writeInt((elementData == EMPTY_ELEMENTDATA) ? 10 : elementData.length);
 
         // Write out all elements in the proper order.
         for (int i=0; i<size; i++)
             s.writeObject(elementData[i]);
 
         if (modCount != expectedModCount) {
             throw new ConcurrentModificationException();
         }
-
     }
 
     /**
      * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,
      * deserialize it).

@@ -721,14 +733,20 @@
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         // Read in size, and any hidden stuff
         s.defaultReadObject();
 
-        // Read in array length and allocate array
-        int arrayLength = s.readInt();
-        Object[] a = elementData = new Object[arrayLength];
+        // Read in array length
+        int initialCapacity = s.readInt();
+        elementData = EMPTY_ELEMENTDATA;
+
+        if((size > 0) || (initialCapacity != 10)) {
+            // allocate array based upon size.
+            ensureCapacityInternal(size);
+        }
 
+        Object[] a = elementData;
         // Read in all elements in the proper order.
         for (int i=0; i<size; i++)
             a[i] = s.readObject();
     }