Java LinkedList去重方法输出异常原因排查
LinkedList去重代码异常:为何b和y被删除而部分a保留?
我写了一段Java代码给LinkedList去重,原列表元素是[a, b, c, a, a, x, y, c, b],但运行后得到的结果是[a, c, x, c]——两个b和y都没了,可还有重复的c,部分a也保留了。我猜是ll.remove()改变索引导致的,但搞不懂为什么会出现这种选择性删除的情况。代码如下:
public void removeDuplicates(LinkedList<String> ll) { for(int i =0; i < ll.size(); i++) { String x = ll.get(i); for(int j = 1; j < ll.size(); j++) { if(ll.get(j) == x) { ll.remove(j); } } } }
问题根源拆解
1. 内层循环起始索引完全错误
你的内层循环从j=1开始,而非j=i+1——这意味着每次处理第i个元素时,会从头(除j=0)开始比较所有元素,包括i之前已经处理过的元素。比如当i=1(当前元素是b)时,j=1就是b本身,直接触发删除,把自己也删掉了,后续索引直接全乱套。
2. 删除元素后未调整j的索引
LinkedList删除元素后,后面的元素会自动前移一位,但你的j会继续递增,直接跳过了原本在j+1位置的元素。比如删除j=3的元素后,原本j=4的元素移到了j=3,但j会直接跳到4,完全没检查这个新移过来的元素。
3. 字符串比较用==而非equals()(非本次异常主因,但属于严重错误)
虽然字符串字面量会存在常量池,==暂时能比较内容,但如果是动态生成的字符串(比如从输入读取),==会比较对象地址而非内容,直接导致去重失效。
核心错误导致的执行结果
我们聚焦关键步骤就能看清b和y的消失原因:
- b被全删:当i=1(当前元素是b)时,内层j从1开始,j=1就是b本身,直接删除自己,列表变成
[a,c,a,x,y,c,b];j继续递增到6时,遇到最后一个b,再次删除,两个b彻底消失。 - y被删除:当i=3(当前元素是y)时,内层j从1开始,j=3就是y本身,触发删除操作,y直接被自己删掉。
- a和c残留重复:因为内层循环起始索引错误,加上删除后j未调整,导致部分重复元素被跳过,比如i=0处理a时,删除两个a后,后续i=2又遇到a,但此时内层循环从j=1开始,删除了当前的a,却漏掉了其他位置的元素交互,最终残留重复的c。
修正后的代码示例
如果要修复这个逻辑,需要:
- 内层循环从
i+1开始,避免重复比较和删除当前元素 - 删除元素后j减1,防止跳过前移的元素
- 用
equals()比较字符串 - (可选)用迭代器或HashSet提升效率
基础修复版本:
public void removeDuplicates(LinkedList<String> ll) { for (int i = 0; i < ll.size(); i++) { String current = ll.get(i); // 只比较当前元素之后的元素 for (int j = i + 1; j < ll.size(); j++) { if (current.equals(ll.get(j))) { ll.remove(j); // 删除后j减1,适配元素前移的索引变化 j--; } } } }
高效版本(用HashSet):
public void removeDuplicates(LinkedList<String> ll) { HashSet<String> seen = new HashSet<>(); Iterator<String> iterator = ll.iterator(); while (iterator.hasNext()) { String element = iterator.next(); if (seen.contains(element)) { iterator.remove(); } else { seen.add(element); } } }
内容的提问来源于stack exchange,提问作者snbmt21
相关产品推荐
相关产品推荐

