In the following example:
public static void main(String[] args){
List<String> list = new ArrayList<String>();
list.add("hi");
list.add("hi");
list.add("hi");
list.remove("hi");
System.out.println(list); //prints [hi, hi]
}
The ArrayList is reduced by one but which one does it remove? Does it remove the last inserted or the earliest inserted one?
Since
List#add()is documented to add to the end of the list, andList#remove(Object)is documented to return the first matching item it encounters, your call above will remove the earliest inserted instance of the string “hi.”Since the printed representation of the three objects in the list are all the same, it’s hard to see the difference in behavior. However, if you look at the instance addresses in a debugger, noting which one entered the list first, you’ll confirm that it’s also the first—and only—one to be removed.
In your case, given that you’re using string literals, they are interned by the compiler (per §3.10.5 of the JLS), so you’ll see three of the same instance present in your list. In order to produce distinct
Stringinstances, try changing your three insertion calls to the following:Compare what you see in the debugger using those statements with your original program. Do you see a difference?
Note that if the
Stringinstancehabove is declared as final, then the three concatenations will in fact all be interned, yielding the sameStringinstance being added to the list three times. Thanks to @xehpuk for correcting my initial mistake regarding the final qualifier.