indexOf()具有重复字符串的奇怪Java.util.List行为

Jor*_*GRC 6 java list

我刚刚遇到了一些奇怪的行为,我不希望ArrayList<String>用Java.当然,这是因为我对Java中的引用的理解不足.

让我告诉你这段代码:

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));
}
Run Code Online (Sandbox Code Playgroud)

这段代码提供以下输出:

0  
1  
1  
3
Run Code Online (Sandbox Code Playgroud)

怎么会?我故意添加了两个包含相同字符("Two")的字符串,但是对象本身不应该是相同的.我在这里误解了什么?我期待这个其他输出:

0
1
2
3
Run Code Online (Sandbox Code Playgroud)

sst*_*tan 12

ArrayList.indexOf()不使用引用相等来查找对象.它使用该equals()方法.注意文档说的内容(强调我的):

返回最低索引i,使得(o == null?get(i)== null:o.equals(get(i))),如果没有这样的索引则返回-1.

因此,它将匹配逻辑上相等的第一个字符串.

编辑:

Andremoniy的评论是绝对正确的.在字符串文字的情况下,因为它们是实习的,所以它们也恰好具有相同的引用.所以你的2个字符串"Two"在这种情况下实际上是相同的引用.

System.out.println("Two" == "Two"); // will return true because they are the same reference.
Run Code Online (Sandbox Code Playgroud)

  • @JorgeGRC如果你的列表很大,使用indexOf()代替一个额外的计数变量会变成一个主要的性能值,因为indexOf()是复杂度O(N),使你的循环与indexOf()在O(N*N)内. (3认同)
  • @JorgeGRC如果需要索引,请使用传统的for循环.没有什么不妥.如果然后返回并查找每个元素的索引,则使用a for each循环最多效率低下. (2认同)