6

Looking through some piece of code I noticed one strange initialization of ArrayList:

... = new ArrayList<..>(0);

I've opened JavaSE 7 sources and saw that inner elementData arrray is initialized by empty array constant - {}. When we pass capacity to the ArrayList constructor we do almost the same - new Object[0]. So my question is: is there is any difference between new ArrayList(0) and new ArrayList() ? Shouldn't ArrayList set the default capacity size to smth like 10 ?

Thanks all for answers.

Jamie Eltringham
  • 810
  • 3
  • 16
  • 25
Dedyshka
  • 421
  • 3
  • 10
  • 20
  • 1
    Possible duplicate of [Why is the default capacity of ArrayList 10?](http://stackoverflow.com/questions/10794890/why-is-the-default-capacity-of-arraylist-10) – Gavriel Feb 08 '16 at 11:28
  • 2
    Apparently it's been changed. These days the default capacity is indeed 0. Well, that's a bit of semantics. When initialized the default capacity is 0, which is increased to 10 if anything is inserted. – Kayaman Feb 08 '16 at 11:29
  • @Gavriel could please point me out where I can find the explanation why default size is 0 in that thread ? – Dedyshka Feb 08 '16 at 11:33
  • 1
    Answered my own question: Initial size is 0 that jumps to 10 upon first use. Initial capacity is 10, but it is lazily loaded. – Neil Feb 08 '16 at 11:34
  • don't mix size and capacity! capacity starts from 10. As long as actual size will be 0-10 the capacity won'y be changed, once you add enough items to make the size bigger than 10, the capacity will be "increased" by creating a new array and copying everything over – Gavriel Feb 08 '16 at 11:38
  • @Gavriel actually I worry about the size of the internal array, especially the case when we're crating a new ArrayList. – Dedyshka Feb 08 '16 at 11:51
  • 1
    FYI; the is this post that could help you : http://stackoverflow.com/questions/34250207/in-java-8-why-is-the-default-capacity-of-arraylist-now-zero – Jesus Zavarce Feb 08 '16 at 12:23

4 Answers4

7

It is necessary to clarify two definitions:

The size represent the number of elements in the list.

The capacity represent the length of the internal array. In other words, the length contains the number of places to put an element;

Exemple of the length of an array list size = 2

When you create one list with the default constructor of Arraylist:

Ex:

List<String> list = new ArrayList<>();
System.out.println(l.size());

The output is : 0

Why?

Because the list is empty, this is explained by the internal array of the list, when you use the default constructor of ArrayList, the internal array is :

private static final Object[] EMPTY_ELEMENTDATA = {}; 

So, an empty array of Objects where the value of the length is 0 (Capacity). As the list is empty the size is 0.

state of the list when the default constructor is used (id of elementData=27)

When you add one element to the list, the size of your list is incremented to 1, and the initial internal array of your list is changed by another array with a length of 10 (capacity); (id of elementData=30)

private static final int DEFAULT_CAPACITY = 10

State of the list after add one element (id of elementData=30)

About the default constructor of ArrayList, the API java says : API Java : https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html#ArrayList%28%29

public ArrayList()

Constructs an empty list with an initial capacity of ten.

In other words, this constructor create an empty list (size equals to 0) with an initial capacity of ten elements.(After add one element to the list, the capacity of the list become 10)

When you know the size of your list, you should create your list with this size. Why? because the complexity of the method add (E element) is O(1) amortized (when there is available space in your list), but O(n) (worst-case) if you add more elements than the initial capacity of your list, in this case, a new array (1.5 times the size) is allocated, and the old array is copied to the new one. Clearly, this operation has costs in terms of performance and memory resources.

So, create a list with an initial capacity of 0 has no sense. If you don't know the initial capacity of your list, use the default constructor that give to you one list with an initial capacity of ten elements.

Keep in mind that definitions of size and capacity around ArrayList are differents:

From book Core Java 2: Fundamentals

Allocating an array list as new ArrayList <'Employee>(100) // capacity is 100

is not the same as allocating a new array as new Employee[100] // size is 100

There is an important distinction between the capacity of an array list and the size of an array. If you allocate an array with 100 entries, then the array has 100 slots, ready for use. An array list with a capacity of 100 elements has the potential of holding 100 elements (and, in fact, more than 100, at the cost of additional reallocations); but at the beginning, even after its initial construction, an array list holds no elements at all.

Jesus Zavarce
  • 1,729
  • 1
  • 17
  • 27
4

An ArrayList has an internal array to store the list elements.

There is a difference between the two constructor calls in Java 7 and 8:

If you do new ArrayList<>(0) the ArrayList creates a new Object array of size 0.

If you do new ArrayList<>() the ArrayList uses a static empty Object array of size 0 and switches to an own private array once you add items to the list.

EDIT:

The Javadoc of the default ArrayList constructor seems to contradict this.

/**
 * Constructs an empty list with an initial capacity of ten.
 */
public ArrayList() {
    super();
    this.elementData = EMPTY_DEFAULTCAPACITY_EMPTY_ELEMENTDATA; // = static, empty
}

But it does not create an element array of length 10 immediately, but instead when you add elements or ensure the capacity:

public void ensureCapacity(int minCapacity) {
    int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
        // any size if not default element table
        ? 0
        // larger than default for default empty table. It's already
        // supposed to be at default size.
        : DEFAULT_CAPACITY; // = 10

    if (minCapacity > minExpand) {
        ensureExplicitCapacity(minCapacity);
    }
}
wero
  • 32,544
  • 3
  • 59
  • 84
  • 1
    Thanks, now I see. I'd also add that that logic resembles the lazy loading - create non-empty array upon first access. – Dedyshka Feb 08 '16 at 11:39
  • I think in the 2nd case capacity starts from 10, not from 0. "ArrayList(): Constructs an empty list with an initial capacity of ten." Not to talk about the `static` array!? Where did you get it from? – Gavriel Feb 08 '16 at 11:39
  • @Dedyshka but it does not make sense to use `new ArrayList(0)` since it creates an array which can never be used – wero Feb 08 '16 at 11:43
  • @Gavriel I did not mention capacity. What do you mean with *capacity starts from 10*? – wero Feb 08 '16 at 11:44
  • @wero, it creates an array with 0 size, and the 1st time you add at least one item into the ArrayList, it'll be thrown away and a new array allocated. – Gavriel Feb 08 '16 at 11:44
  • 2
    @Gavriel yes that is case 1. In case 2 it uses `DEFAULTCAPACITY_EMPTY_ELEMENTDATA` which is static (look at the source). The capacity increment can be different though when items are added or capacity is ensured. – wero Feb 08 '16 at 11:48
  • @wero I agree. If I use new ArrayList() it'll be pointing to internal EMPTY_ELEMENTDATA, and as soon as it adds element I'll create a new array and start using the last one. In case of new ArrayList(0) it'll create a new empty array from the start and will create a new one again when new element has been added. Am I right ? – Dedyshka Feb 08 '16 at 11:49
  • @wero, you're right, the documentation is not up-to-date with the code! – Gavriel Feb 08 '16 at 11:51
1

ArrayList has 2 constructors. The default constructor just calls the other one with capacity=10:

ArrayList() {this(10);}

ArrayList(capacity)

What capacity means? It means that an array of the size capacity is allocated to hold the items in the arraylist. Whenever it's too small to hold the necessary items, it's being resized, by creating a bigger array and copying everything over (takes time) + it means the old array needs to be garbage collected (even more time). That's why it is important to get the correct capacity right. Although it will work with any initial capacity, it can be slow. On the other hand having huge capacity and almost no items in it is wasting memory.

Note: Arraylist(0) will create a 0 size array, and when you try to add the 1st element, it'll be thrown away and a new array allocated.

Gavriel
  • 18,880
  • 12
  • 68
  • 105
1

ArrayList() will make list capacity of 10 (default) after first element added. However ArrayList(0) will keep capacity small - it will be 1 after first element added, 2 after the second add, and etc.

Ruslanas
  • 61
  • 6