为何两段相似Java列表访问代码测试结果不同?求原因解析
Hackerrank Minimum Distances代码差异问题
我正在解决Hackerrank的minimum-distances问题(给定一个列表,找出任意两个相等元素之间的最小距离)。编写的第一段代码无法通过部分测试用例,但将a.get(i)提取到内层循环前的变量后,所有测试用例都通过了(本地也能复现此情况),想知道两者差异的原因,是否是汇编层面优化导致的?
无法通过部分测试用例的代码
public static int minimumDistances(List<Integer> a) { int min = Integer.MAX_VALUE; boolean hasPair = false; for(int i = 0 ; i < a.size()-1; i ++){ for(int j = i+1; j < a.size() ; j++){ if(a.get(i) == a.get(j) && j-i < min){ min = j-i; hasPair = true; } } } if(!hasPair) min = -1; return min; }
所有测试用例通过的代码
public static int minimumDistances(List<Integer> a) { int min = Integer.MAX_VALUE; boolean hasPair = false; for(int i = 0 ; i < a.size()-1; i ++){ int current = a.get(i); for(int j = i+1; j < a.size() ; j++){ if(current == a.get(j) && j-i < min){ min = j-i; hasPair = true; } } } if(!hasPair) min = -1; return min; }
差异原因解析
这和汇编层面优化无关,核心问题在于**Integer对象的引用比较逻辑与多次List.get()调用的潜在问题**:
- 第一段代码内层循环每次判断都调用
a.get(i),当列表元素是超出-128~127范围的Integer时,自动装箱会生成不同的对象实例。此时用==比较的是对象引用,而非数值大小——哪怕两个元素数值相等,只要是不同的Integer对象,==就会返回false,导致程序漏掉应该匹配的元素对,无法计算出正确的最小距离。 - 第二段代码提前将
a.get(i)的数值拆箱存入int类型的current变量,后续与a.get(j)比较时,a.get(j)会自动拆箱为int,此时==比较的是数值本身,逻辑完全正确。 - 此外,如果传入的
List是可变的(比如多线程场景下被修改),多次调用a.get(i)可能返回不同值,提前存到变量里能避免这种风险,同时还减少了重复的get调用开销。
内容的提问来源于stack exchange,提问作者manofaction
相关产品推荐
相关产品推荐

