14

While working on ArrayList, I found after setting the initial size of array using the constructor with initialCapacity, then use set() will throw an exception although the array is created, but size isn't set correctly.

Using ensureCapacity() won't work either because it is based on the elementData array instead of size.

There are other side effects because of the static DEFAULT_CAPACITY with ensureCapacity().

The only way to make this work is to use add() as many time as required after using the constructor.

Please check the code below.

import java.util.ArrayList;
import java.util.List;

public class Test {

public static void main(String[] args) {

    List test = new ArrayList(10);
    test.set(5, "test");
    System.out.println(test.size());
}

I am not sure why java is throwing this exception.

Behaviour I expected: test.size() should return 10 and set(5, ...) should work.

ACTUAL: throws an Exception IndexOutOfBoundsException.

So is it set method that is causing problem ?

T-Bag
  • 10,916
  • 3
  • 54
  • 118
  • There is no 'peculiar behaviour of `ArrayList.size()` 'here. You're not even getting there. – user207421 Dec 30 '15 at 09:21
  • Ok , Will change the title – T-Bag Dec 30 '15 at 10:07
  • 1
    Possible duplicate of [ArrayList initial capacity and IndexOutOfBoundsException](http://stackoverflow.com/questions/11908037/arraylist-initial-capacity-and-indexoutofboundsexception) – Roddy of the Frozen Peas Dec 30 '15 at 21:13
  • I am not convinced by the answer provided there , Answer provided by ERAN i think is much simpler and self explanatory. Hence not a duplicate – T-Bag Dec 31 '15 at 06:28
  • This is a duplicate of the much clearer question and answer in https://stackoverflow.com/questions/8896758/initial-size-for-the-arraylist – Mike Ryan Aug 29 '18 at 17:39

6 Answers6

23

test.set(5, "test"); is the statement that throws this exception, since your ArrayList is empty (size() would return 0 if you got to that statement), and you can't set the i'th element if it doesn't already contain a value. You must add at least 6 elements to your ArrayList in order for test.set(5, "test"); to be valid.

new ArrayList(10) doesn't create an ArrayList whose size is 10. It creates an empty ArrayList whose initial capacity is 10.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • I updated my question , it was not properly explained before please check now – T-Bag Dec 30 '15 at 09:19
  • 7
    @ShowStopper What's not properly explained? An ArrayList is initialized to a 0 length, regardless of its initial capacity, unless you are using a constructor that initializes the ArrayList with the elements of another Collection. – Eran Dec 30 '15 at 09:21
10

The exception is not thrown by test.size() but by test.set(5, "test");. This is because you are setting an element at index 5 but the list is currently empty.

List test = new ArrayList(10);

does not create a list initialized with 10 null elements. It creates a list that has an initial capacity of 10 elements, that is the backing array has a size of 10, but the list itself is still empty.

If you want to initialize a list with 10 null elements, you can use

List<String> list = new ArrayList<>(Collections.nCopies(10, null));

As a side note, you should never use raw types like List but always prefer a parameterized list.

Community
  • 1
  • 1
Tunaki
  • 132,869
  • 46
  • 340
  • 423
3

List test = new ArrayList(10); creates empty list which would have capacity of 10 elements.It is not containing element at 6th position so you will not be able to set element at this position.

Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
2

List test = new ArrayList(10); creates empty ArrayList of raw types (Object) with initial capacity(capacity of list initially, initialize internal array with length 10) not to be confused with size(number of elements list contains).

To understand more first note that ArrayList is nothing but manipulation of array to dynamically change size of the array which we were not able to do with array directly. Ultimately, it's a smart array.

By setting initial capacity we are telling ArrayList to create size of array 10 initially (by default initial capacity is 10).

This is what constructor is doing,

public ArrayList(int initialCapacity) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    this.elementData = new Object[initialCapacity];//creates initial array
}

You can increase or decrease it accordingly, say you are sure that you are going to need list with 20 elements it'll be better to set initial capacity at start. It avoids resizing of array if you are sure about minimum number of elements you will definitely have in list.

test.set(5, "test"); method replaces element at specific position here it will going to replace element at index 5 with test. But our list is empty, it does not have any element.

Documentation of this method says,

IndexOutOfBoundsException - if the index is out of range (index < 0 || index >= size())

Note that size of list is 0 so index (5) is greater than size(0).

akash
  • 22,664
  • 11
  • 59
  • 87
0

Replaces the element at the specified position in this list with the specified element.

set

Parameters

index int: index of the element to replace

element E: element to be stored at the specified position

Returns E the element previously at the specified position

Throws

IndexOutOfBoundsException
nzala
  • 374
  • 4
  • 10
0

The thing is that your list "Test" is empty and when you are trying to

execute this statement test.set(5, "test"); it won't be able to set that

value in the list & will show Out of bounds exception as it will not create 10 empty spaces.

So, you can initialize your list before:

for(int i=0;i<10;i++)  // As you took ten in your code
 
{
test.add(null);   // some people also use test.add(0) instead of null , 
                 //but '0' also contains a value & considering your code please use null   
}