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

Print this page
rev 6789 : 7143928: 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

@@ -102,17 +102,24 @@
 public class ArrayList<E> extends AbstractList<E>
         implements List<E>, RandomAccess, Cloneable, java.io.Serializable
 {
     private static final long serialVersionUID = 8683452581122892189L;
 
+    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;
 
     /**
+     * initial capacity.
+     */
+    private transient int initialCapacity;
+
+    /**
      * The size of the ArrayList (the number of elements it contains).
      *
      * @serial
      */
     private int size;

@@ -127,11 +134,12 @@
     public ArrayList(int initialCapacity) {
         super();
         if (initialCapacity < 0)
             throw new IllegalArgumentException("Illegal Capacity: "+
                                                initialCapacity);
-        this.elementData = new Object[initialCapacity];
+        this.initialCapacity = initialCapacity;
+        elementData = EMPTY_ELEMENTDATA;
     }
 
     /**
      * Constructs an empty list with an initial capacity of ten.
      */

@@ -160,12 +168,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);
         }
     }
 
     /**

@@ -174,16 +181,25 @@
      * specified by the minimum capacity argument.
      *
      * @param   minCapacity   the desired minimum capacity
      */
     public void ensureCapacity(int minCapacity) {
+        if(elementData != EMPTY_ELEMENTDATA) {
         if (minCapacity > 0)
             ensureCapacityInternal(minCapacity);
+        } else {
+            // adjust eventual capacity if requested capacity is larger.
+            initialCapacity = Math.max(initialCapacity, minCapacity);
+        }
     }
 
     private void ensureCapacityInternal(int minCapacity) {
         modCount++;
+        if(elementData == EMPTY_ELEMENTDATA) {
+            minCapacity = Math.max(initialCapacity, minCapacity);
+        }
+
         // overflow-conscious code
         if (minCapacity - elementData.length > 0)
             grow(minCapacity);
     }
 

@@ -700,20 +716,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) ? initialCapacity : 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,15 +736,19 @@
     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
+        initialCapacity = s.readInt();
+        elementData = EMPTY_ELEMENTDATA;
+
+        // allocate array based upon size.
+        ensureCapacityInternal(size);
 
-        // Read in all elements in the proper order.
+        Object[] a = elementData;
+        // Read in all elements  the proper order.
         for (int i=0; i<size; i++)
             a[i] = s.readObject();
     }
 
     /**