tags:

views:

115

answers:

4

Consider the following two snippets of code:

int index = 676;
List<String> strings = new ArrayList<String>();
strings.add(index, "foo");

and

int index = 676;
List<String> strings = new ArrayList<String>();
strings.ensureCapacity(index);
strings.add(index, "foo");

In the first case, I'm not surprised to see an IndexOfOutBoundsException. According to the API, add(int index, E element) will throw an IndexOfOutBoundsException "if the index is out of range (index < 0 || index > size())". The size of strings is 0 before any elements have been added, so index will definitely be larger than the ArrayList's size.

However, in the second case, I would expect the call to ensureCapacity to grow strings such that the call to add would correctly insert the string "foo" at index 676 - but it doesn't.

  1. Why not?

  2. What should I do so that add(index, "foo") works for index > strings.size()?

+3  A: 

The capacity of the underlying array in an ArrayList is distinct from the higher-level List API methods (add, remove, etc.), and only speaks to the size of the backing array. If you want to allow adding elements beyond the list bounds, you'll need to code that yourself (or find a collection that does it for you) in a utility class, populating nulls, empty objects, or whatever your application expects between the new index and the old size.

CapnNefarious
This is the correct answer. The `ensureCapacity()` method is there for performance reasons. Allowing `ArrayList` to automatically resize the backing array as new elements are added can be slow in some circumstances, since the array must be reallocated each time the new list length exceeds the backing array's length. With `ensureCapacity()` you can say "I am going to have at least *N* number of elements, so start off with a backing array of *N* elements."
William Brendel
+2  A: 

ArrayList.ensureCapacity() does not change the actual size of the list (which is returned by size()), but rather reallocate the internal buffer such that it will not need to reallocate the buffer to grow to this size (when you call list.add(object).

/**
 * Increases the capacity of this <tt>ArrayList</tt> instance, if
 * necessary, to ensure that it can hold at least the number of elements
 * specified by the minimum capacity argument.
 */
Omry
+2  A: 

Taking a wild guess, I think what you're looking for is

Integer index = Integer.valueOf(676);
Map<Integer,String> strings = new HashMap<Integer,String>();
strings.put(index, "foo");
Robert Munteanu
It's funny you should mention this. I started out using a Map, and in my long-day-of-coding clouded thinking ended up switching to a List (last night). After getting about halfway through implementing resizing the List, I just now switched back to a Map.
Matt Ball
A: 

your length is 676, but you have to remember that they are zero based, so in reality, you'd want index -1 would be your max number.

SacramentoJoe