Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java ArrayList remove object - IndexOutOfBoundsException

Tags:

java

arraylist

I am trying to remove an object from an ArrayList, but I keep getting an IndexOutOfBounds Error. Now there is plenty information available why this happens when iterating over the ArrayList while removing, however I'm not doing that. Example:

 ArrayList<Character> a = new ArrayList<Character>();
 a.add('A');
 a.add('B');
 a.add('C');
 System.out.println(a);
 a.remove('A');
 System.out.println(a);

prints [A, B, C] and then fails with:

java.lang.IndexOutOfBoundsException: Index: 65, Size: 3
    at java.util.ArrayList.rangeCheck(ArrayList.java:635)
    at java.util.ArrayList.remove(ArrayList.java:474)
    at b.<init>(b.java:23)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at bluej.runtime.ExecServer$3.run(ExecServer.java:746)

Why is this happening?

EDIT to clarify this question is not a duplicate of this question:

The specific problem that is occuring here has nothing to do with the usual problems when removing elements while iterating. It is rather caused by the overloaded ArrayList remove method and the automatic type conversion from char to int by java.

This aspect is not covered in the answer of the other question.

like image 639
Stefan Avatar asked Jan 06 '16 21:01

Stefan


People also ask

How do you remove an object from an ArrayList in Java?

There are two ways to remove objects from ArrayList in Java, first, by using the remove() method, and second by using Iterator. ArrayList provides overloaded remove() method, one accepts the index of the object to be removed i.e. remove(int index), and the other accept objects to be removed, i.e. remove(Object obj).

Can we remove an object from ArrayList?

There are 3 ways to remove an element from ArrayList as listed which later on will be revealed as follows: Using remove() method by indexes(default) Using remove() method by values. Using remove() method over iterators.

Does ArrayList remove use equals?

ArrayList remove() relies on the objects implementation of the Equal method. If no implementation has been done then the object is removed by Object 's implementation of Equals which indeed is the pointer comparison.

What causes Java Lang IndexOutOfBoundsException?

IndexOutOfBoundsException is a subclass of RuntimeException mean it is an unchecked exception which is thrown to indicate that an index of some sort (such as to an array, to a string, or to a vector) is out of range.


1 Answers

There are 2 overloaded remove methods -- one that takes an int as an index, and one that takes an Object, to remove the object reference itself.

Section 15.12.2 of the JLS covers how Java chooses one method overload over another.

The phases are:

  1. The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

This guarantees that any calls that were valid in the Java programming language before Java SE 5.0 are not considered ambiguous as the result of the introduction of variable arity methods, implicit boxing and/or unboxing. However, the declaration of a variable arity method (§8.4.1) can change the method chosen for a given method method invocation expression, because a variable arity method is treated as a fixed arity method in the first phase. For example, declaring m(Object...) in a class which already declares m(Object) causes m(Object) to no longer be chosen for some invocation expressions (such as m(null)), as m(Object[]) is more specific.

  1. The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.

This ensures that a method is never chosen through variable arity method invocation if it is applicable through fixed arity method invocation.

  1. The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.

(bold emphasis mine)

Both methods are applicable here, because a char can be promoted to an int, but it can also be boxed to a Character, matching a's type parameter. But Java will choose promotion alone before any method that requires boxing, so 'A' is promoted to int, hence the value 65.

You can cast it explicitly to Character if you want to remove by object reference.

a.remove((Character) 'A');
like image 115
rgettman Avatar answered Sep 25 '22 23:09

rgettman