11

Here is a very simple test that fails with a

System.ListException: List index out of bounds: 0

Sample code:

List<integer> intList = new List<integer>();
intList.add(0, 2);

This seems very odd to me, shouldn't it just put the integer 2 into the currently empty list? The exception occurs whenever the index parameter equals the current list size. I'd expect the exception if the index was greater than the current list size or less than zero.

Now when I want to insert something at the start of the list I need to first check if the list is empty. E.g.

public void someMethod(List<integer> existingList) {
    // Existing code ...
    integer intToPrepend = 1;

    // Insert at start of the list
    if(existingList.isEmpty()) {
        existingList.add(intToPrepend);
    } else {
        existingList.add(0, intToPrepend);
    }
}

Should it be possible to use add(Integer, Object) to append an element to the end of a list?


Part of my confusion probably comes from my .NET background and the following C# not throwing an ArgumentOutOfRangeException.

List<int> intList = new List<int>();
intList.Insert(0, 2);

4 Answers 4

7

It'd be nice if it added it, but I think you hit the nail on the head with:

I'd expect the exception if the index was greater than the current list size or less than zero.

If it was greater than the list size then it'd definitely be out of bounds, but with zero-based counting then it'd be out of bounds if it's equal to the size also.

| 0 | 1 | 2 | <-Size is 3 but 3 would be OOB

I guess both set() and add() assume the index specified already exists. Whether you should be able to add to a list this way comes down to the specification of the class and method, though personally I think you should expect it to function the way it does.

If it automatically allocated space in memory for the case when index is 0, then it should also do that when the index is 100,000 and as such programmer mistakes could lead to vast swathes of wasted memory. It'd probably just be size * sizeof(reference)) and not catastrophic, but I think the reasoning is valid.

4
  • I think my confusion comes from how the .NET List<X>.Insert(int index, X item) method works. It will append to the end of the list if the index equals the current list size and throw an exception if it is greater. Commented Sep 25, 2013 at 20:02
  • Also, I'm no Java expert, but from the List<E>.add(int index, E element) docs: "Throws: IndexOutOfBoundsException - if the index is out of range (index < 0 || index > size())". In apex it appears the ListException occurs for index < 0 || index >= size() Commented Sep 25, 2013 at 20:05
  • The docs do not specify that you can't use the two parameter form on an empty list, so I'd call this a bug. Regardless, you should probably encounter this less frequently than you'd expect.
    – sfdcfox
    Commented Sep 25, 2013 at 21:02
  • @sfdcfox: I just encountered it in a situation where I needed to build a list in reverse order, so I'm inserting elements at index 0. Having to check if the list is empty and include that special case inside the loop is unfortunate. I provided feedback on the documentation page to specifically mention that this method does not work on empty lists.
    – tomlogic
    Commented Nov 21, 2013 at 18:07
5

listInstance.add(Integer, Object) method is for adding new value at existing position index. e.g;

This won't give exception:

List <integer> i = new List<integer>();

i.add(0);
i.add(0,1);

But this:

List <integer> i = new List<integer>();
i.add(0,1); // there is no index `0`

Because at this point list size is 0. So there should not be any index position to filled or replace. As you add an element to the list it size become 1 means it now have position index start from 0. So 0 is open to replace/add or remove.

However after adding element at 0 position its next index position is open to fill because new position has been allocated to shifted item and list size is increased by 1.

List <integer> i = new List<integer>();

i.add(0);
i.add(0,1);
i.add(1,1);
i.add(2,1);

We can add element to the next position to the current max index only.

If you want add element to last position:

Integer lastEle = i.size()-1; 
if(lastEle != -1)
{
   i.add(lastEle ,25);
}
2
  • 1
    "replacing" probably isn't the term to use for what .add(Integer, Object) is doing. If that were the case then the list size would remain unchanged afterwards, which isn't the case. Commented Sep 25, 2013 at 19:58
  • @DanielBallinger Yes, I corrected it in my answer. Thanks.
    – Ashwani
    Commented Sep 26, 2013 at 5:45
0

I got around this by declaring the list like this:

List<SObject> objects = new SObject[1];
objects.add(0, element);

After declaring the list with at least a size of one the .add(0, element) adds the element at the first index. Keep in mind that the list will contain a null object at the end. Which I guess you could remove, but in my case, the list is of SelectOption and the null object doesn't show in the dropdown options.

Hope it helps.

-2

I think here you wanna use Set method

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_System_List_set.htm

1
  • I think you missed the point of Daneil's question — regardless, the set() method does the same thing.
    – Matt Lacey
    Commented Sep 25, 2013 at 7:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .