The int vs. Integer pitfall of Java's ArrayList.remove()

awwsmm profile image Andrew (he/him) ・1 min read

Be careful when you try to use ArrayList.remove() to delete specific elements using a boxed Integer rather than a primitive int -- you probably won't get the result you expect:

jshell> ArrayList alist = new ArrayList(Arrays.asList('a', 'b', 'c', 'd', 'e'))
alist ==> [a, b, c, d, e]

jshell> alist.remove((Integer)3)
$2 ==> false

jshell> alist
alist ==> [a, b, c, d, e]

...this is because ArrayList has two remove() methods. One which takes a java.lang.Object, and one which takes a primitive int.

jshell> alist.remove(3)
$4 ==> 'd'

jshell> alist
alist ==> [a, b, c, e]

When you use the former one, Java tries to match the Integer object in your list, rather than removing the object at the specified index. In most cases, this will not be what you want. Be especially careful when doing things like:

jshell> ArrayList toDelete = new ArrayList(Arrays.asList(0, 2))
toDelete ==> [0, 2]

jshell> for (Integer ii : toDelete) alist.remove(ii)

jshell> alist
alist ==> [a, b, c, e]

Here, we get no hint within the jshell that something went wrong (like we did above when remove() returned false). Make sure to always loop over primitive ints:

jshell> for (int ii : toDelete) alist.remove(ii)

jshell> alist
alist ==> [b, c]

This post originally appeared in a slightly different form on my (now defunct) Wordpress blog.


Editor guide
djtai profile image
πŸ‡¬πŸ‡ΊπŸ‡²πŸ‡΅ David Taitingfong

Ahh, that is interesting. So...if it's not an int index then it's looking for a specific Object? This seems like a good Java interview question - pretty tricky IMO.

awwsmm profile image
Andrew (he/him) Author

Yep! Integer is a subclass of Object, so Java assumes you're looking for a specific Integer object in your ArrayList, even if the actual subclass is something totally different, like Character.