Reputation: 15968
Is there historical reasons to the two ambiguous List.remove
?
It seems like terrible design to me.
For a List<Integer>
it just seems really confusing.
EDIT:
Everybody seems pretty fine with this. Let me precise things a bit.
Let's say I have a List<Boolean>
.
Integer idx = Integer.valueOf(2);
list.remove(idx)
Though idx
is an object, Java compiles and will remove the item at index 2.
Now if it had been a List<Integer>
, the very same code would have called a different method with a totally different behavior.
Let's not talk about what would happen with Generics.
I feel like different behavior implies different names is a precious rule, especially within the same class.
Upvotes: 8
Views: 612
Reputation: 14548
One of them is for removing from specific index
The other is removing an object, index is not important.
Upvotes: 0
Reputation: 40851
Yep, this exact case is frequently cited as an example of how perfectly well-intentioned language changes (generics, autoboxing) can combine with each other and with existing APIs to produce bugs. Indeed Josh wishes he had given the methods different names, but when that interface was first created, it was never imagined that there could be any conflict between an Object and an int. You can find an exploration of this issue in Java Puzzlers (Bloch/Gafter).
Upvotes: 3
Reputation: 308031
First of all:
List.remove(int)
removes an element at the specified index andList.remove(Object)
(or Collection.remove(Object)
) removes the specified element.I'm not sure if this was already known, but for completeness sake, I thought I'd mention it.
An important part to notice is that the API predates generics (and more importantly) auto-boxing by quite a bit (the collections API was introduced in Java 1.2 and auto-boxing was introduced in Java 5).
So when they first designed the API, there was absolutely no way to confuse the two. Even if your List
contained Integer
objects, it's simple: if you call the method with a primitive argument type (int
), then it's the index, if you pass in an Object
(even if it's Integer
), then you pass in the object to remove.
Granted, it's still not the greatest idea (but quite a few Java APIs are ... less than perfect), but the chance for confusion was much lower back then.
The increased chance of confusion only exists since the int
/Integer
barrier became less visible thanks to auto-boxing and auto-unboxing.
Sidenote: an important "feature" of the collections API is "short names for commonly used methods". The previous "solution" of Vector
/Enumeration
had notoriously long names for pretty common operations:
Vector.elementAt()
vs. List.get()
Vector.addElement()
vs. Collection.add()
Enumeration.hasMoreElements()
/nextElement()
vs. Iterator.hasNext()
/next()
Vector.removeElement()
vs. Collection.remove()
Vector.removeElementAt()
vs. List.remove(int)
And the last one are where they probably went a bit too far.
Upvotes: 11
Reputation: 120188
What, this is not ambigious at all. One removes at a specified index, the other removes an object where-ever it is first found in the list... oO
EDIT - the definition of a method is more than just the name. The type and number of arguments is part of the definition. When you take the entire method definition, there is no ambiguity.
Upvotes: 0
Reputation: 139931
How is this ambiguous? The documentation of each method seems clear to me:
E remove(int index)
Removes the element at the specified position in this list (optional operation).
boolean remove(Object o)
Removes the first occurrence in this list of the specified element (optional operation). If this list does not contain the element, it is unchanged.
They do two completely different things, hence a need for both.
Upvotes: -3