MOOC Java ArrayList存Item按identifier去重失败问题修复
问题现象
程序无法正确校验ArrayList中已存储Item对象的identifier属性值,在TMC环境运行时2个测试用例失败:相同identifier的Item被重复添加到ArrayList,不符合题目要求的「identifier唯一、重复录入保留首次添加项」规则。
题目要求
修改程序使录入的Item打印时每个最多出现1次,规则如下:
- 两个Item只要identifier相同即判定为重复(name可存在差异)
- 重复录入则保留并打印首次添加的Item
- 仅打印Item内容时使用冒号拼接identifier和name字段
失败用例详情
- 测试用例
printingTwoEqualItemsOnlyPrintsOneItem失败:输入序列为identifier、item2、identifier、item2时,实际输出2个重复项[identifier: item2, identifier: item2],预期仅输出1个Item。 - 测试用例
printingTwoItemsWithDifferentNamesButSameIdentifiersOnlyContainsOneItem失败:输入序列为identifier、item1、identifier、item2时,实际输出2个同identifier不同name的项[identifier: item1, identifier: item2],预期仅输出1个Item。
现有代码
Main类
import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { ArrayList<Item> archive = new ArrayList<>(); Scanner scanner = new Scanner(System.in); while (true) { System.out.println("Identifer?(empty will stop)"); String identifier = scanner.nextLine(); if (identifier.equals("")) { break; } System.out.println("Name?(empty will stop)"); String name = scanner.nextLine(); if (name.equals("")) { break; } Item item1 = new Item(identifier, name); if (archive.contains(item1.identifier)){ continue; } archive.add(item1); } System.out.println("==items=="); for (Item item : archive) { System.out.println(item.toString()); } } }
Item类
public class Item { String identifier; String name; @Override public String toString() { return identifier + ": " + name; } Item(String i, String n){ this.identifier = i; this.name = n; } }
根因分析
原去重逻辑存在类型匹配错误:archive是声明为ArrayList<Item>的泛型集合,存储元素全为Item类型对象,但代码中调用archive.contains(item1.identifier)时传入的参数是String类型的identifier值。contains()方法会逐一遍历集合内元素,调用元素的equals()方法和传入参数做相等判断,Item对象和String对象永远不可能返回相等结果,因此判断逻辑永远返回false,去重完全失效,重复元素会被正常加入集合。
修复方案
核心是修正错误的去重判断逻辑,不再直接给存储Item类型的ArrayList传String类型参数调用contains,改为遍历集合匹配已有Item的identifier属性,匹配到重复项则跳过添加。
修复后完整Main类代码
import java.util.ArrayList; import java.util.Scanner; public class Main { public static void main(String[] args) { ArrayList<Item> archive = new ArrayList<>(); Scanner scanner = new Scanner(System.in); while (true) { System.out.println("Identifier?(empty will stop)"); String identifier = scanner.nextLine(); if (identifier.isEmpty()) { break; } System.out.println("Name?(empty will stop)"); String name = scanner.nextLine(); if (name.isEmpty()) { break; } Item newItem = new Item(identifier, name); boolean isDuplicate = false; for (Item existItem : archive) { if (existItem.identifier.equals(identifier)) { isDuplicate = true; break; } } if (isDuplicate) { continue; } archive.add(newItem); } System.out.println("==items=="); for (Item item : archive) { System.out.println(item); } } }
调整点说明
- 修正了控制台提示文本中
Identifer的拼写错误为标准拼写Identifier - 移除原错误的
archive.contains(item1.identifier)判断,替换为遍历集合逐一对已有Item的identifier属性做等值匹配,从根本上解决类型不匹配导致的去重失效问题 - 空字符串判断使用
isEmpty()替代equals(""),符合Java常规编码规范 - 打印逻辑无需手动调用
toString(),println方法会自动调用对象的toString方法输出格式化内容 - 现有Item类的逻辑完全符合题目要求:toString方法已按规则使用冒号拼接identifier和name,构造方法赋值逻辑正确,无需修改。
内容的提问来源于stack exchange,提问作者j-laze
相关产品推荐
相关产品推荐

