Reputation: 15808
When I do
ArrayList<Integer> arr = new ArrayList<Integer>(10);
arr.set(0, 1);
Java gives me
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.set(Unknown Source)
at HelloWorld.main(HelloWorld.java:13)
Is there an easy way I can pre-reserve the size of ArrayList and then use the indices immediately, just like arrays?
Upvotes: 27
Views: 7757
Reputation: 14699
Here's the source from ArrayList
:
The constructor:
public ArrayList(int initialCapacity)
{
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
this.elementData = new Object[initialCapacity];
}
You called set(int, E)
:
public E set(int index, E element)
{
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
Set
calls rangeCheck(int)
:
private void rangeCheck(int index)
{
if (index >= size) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
It may be subtle, but when you called the constructor, despite initializing an Object[]
, you did not initialize size
. Hence, from rangeCheck
, you get the IndexOutOfBoundsException
, since size
is 0. Instead of using set(int, E)
, you can use add(E e)
(adds e
of type E
to the end of the list, in your case: add(1)
) and this won't occur. Or, if it suits you, you could initialize all elements to 0 as suggested in another answer.
Upvotes: 15
Reputation: 22251
Programming aside, what you are trying to do here is illogical.
Imagine an empty egg carton with space for ten eggs. That is more or less what you have created. Then you tell a super-precise-and-annoying-which-does-exactly-what-you-tell-him robot to replace the 0th egg with another egg. The robot reports an error. Why? He can't replace the 0th egg, because there is no egg there! There is a space reserved for 10 eggs, but there are really no eggs inside!
Upvotes: 2
Reputation: 7899
Capacity is used to prepare ArrayList
s for expansion. Take the loop
List<Integer> list = new ArrayList<>();
for(final int i = 0; i < 1024; ++i) {
list.add(i);
}
list
starts off with a capacity of 10
. Therefore it holds a new Integer[10]
inside. As the loop adds to the list, the integers are added to that array. When the array is filled and another number is added, a new array is allocated twice the size of the old one, and the old values are copied to the new ones. Adding an item is O(1) at best, and O(N) at worst. But adding N items will take about 2*1024
individual assignments: amortized linear time.
Capacity isn't size. If you haven't added to the array list yet, the size will be zero, and attempting to write into the 3rd element will fail.
Upvotes: 0
Reputation: 3820
This is not an Java-specific answer but an data structure answer.
You are confusing the Capacity
concept with the Count
(or Size
) one.
Capacity is when you tell the list to reserve/preallocate a number of slots in advance (in this ArrayList case, you are saying to it create an array of 10 positions) in its' internal storage. When this happens, the list still does not have any items.
Size (or Count) is the quantity of items the list really have. In your code, you really doesn't added any item - so the IndexOutOfBoundException is deserved.
Upvotes: 1
Reputation: 1303
While you can't do what you want with arraylist, there is another option: Arrays.asList()
Upvotes: 0
Reputation: 48817
You could use arr.add(1)
, which will add 1
in the first empty cell, i.e. the 0-indexed one.
Or you could create your own list:
public static class PresetArrayList<E> extends ArrayList<E> {
private static final long serialVersionUID = 1L;
public PresetArrayList(int initialCapacity) {
super(initialCapacity);
addAll(Collections.nCopies(initialCapacity, (E) null));
}
}
Then:
List<Integer> list = new PresetArrayList<Integer>(5);
list.set(3, 1);
System.out.println(list);
Prints:
[null, null, null, 1, null]
Upvotes: 1
Reputation: 6390
I believe the issue here is that although you have suggested the allocated space of entries in the Array, you have not actually created entries.
What does arr.size()
return?
I think you need to use the add(T) method instead.
Upvotes: 3
Reputation: 27792
How about this:
ArrayList<Integer> arr = new ArrayList<Integer>(Collections.nCopies(10, 0));
This will initialize arr with 10 zero's. Then you can feel free to use the indexes immediately.
Upvotes: 25