I've just come across some odd behaviour I wouldn't expect from an ArrayList<String>
in Java. This is coming, for sure, from my poor understanding of references in Java.
Let me show you this piece of code:
List<String> myList = new ArrayList<>();
myList.add("One");
myList.add("Two");
myList.add("Two");
myList.add("Three");
for (String s : myList){
System.out.println(myList.indexOf(s));
}
This piece of code provides the following output:
0
1
1
3
How come? I've added on purpose two Strings containing the same characters ("Two"), but the object itself shouldn't be the same. What am I misunderstanding here? I was expecting this other output:
0
1
2
3
The indexOf() method returns the position of the first occurrence of specified character(s) in a string. Tip: Use the lastIndexOf method to return the position of the last occurrence of specified character(s) in a string.
All you need to know is that Set doesn't allow duplicates in Java. Which means if you have added an element into Set and trying to insert duplicate element again, it will not be allowed. In Java, you can use the HashSet class to solve this problem.
ArrayList.indexOf() doesn't use reference equality to find the object. It uses the equals()
method. Notice what the documentation says (emphasis mine):
returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
Thus, it will match on the first string that is logically equal.
EDIT:
Andremoniy
's comment is absolutely right. In the case of strings literals, because they are interned, they will also happen to have the same reference. So your 2 strings "Two"
are actually the same reference in this case.
System.out.println("Two" == "Two"); // will return true because they are the same reference.
It's simply because indexOf
returns the first occurrence of the item in the list that is equal to the given string. See its documentation:
Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element. More formally, returns the lowest index
i
such that(o==null ? get(i)==null : o.equals(get(i)))
, or -1 if there is no such index.
You'll have to note two points:
"Two"
gets interned, that is all occurences of this literal will refer to the same instance.List.indexOf()
doesn't compare items by ==
(that is object-identity) but using equals()
- that is some class-defined way to compare two objects for equality (which makes perfect sense as otherwise you wouldn't be able to find something in the list unless you already have a reference to it). So even two different String
-objects (e.g. created by new String("Two")
) would still produce the same output.For completeness the quote from the javadoc of indexOf
(as already mentioned in the other answers:
returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i))), or -1 if there is no such index.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With