Java如何基于ID校验防止向ArrayList存入重复Book对象
代码判重逻辑失效的原因
你的库存列表inventory泛型为Book类型,调用contains(id)时传入的int类型图书ID会被自动装箱为Integer对象。而ArrayList的contains方法本质是遍历列表存储的所有元素,将传入的对象和每个元素做equals匹配——Integer和Book属于完全不同的类型,永远不可能相等,因此无论库存中是否存在相同ID的图书,inventory.contains(id)都会返回false,判重逻辑自然完全不生效。
可行实现方案
方案1:手动遍历库存列表匹配ID(改动最小,无需额外修改类结构)
这是最直观的实现方式,不需要调整原有类的方法结构,改动成本最低:
- 首先确保
Book类提供公开的ID获取方法,例如public int getId() { return id; } - 将
addBook方法中的原有判断逻辑替换为如下代码:
// 标记是否存在重复ID的图书 boolean isDuplicated = false; for (Book storedBook : inventory) { if (storedBook.getId() == id) { isDuplicated = true; break; } } if (isDuplicated) { System.out.println("This book is already in the inventory!"); // 发现重复直接终止当前方法执行,跳过后续录入流程 return; } // 以下为原有新图书录入逻辑 System.out.print("Enter book title: "); // 读取数字输入后清空缓冲区残留的换行符,避免书名读取异常 scan.nextLine(); String title = scan.nextLine(); System.out.print("Enter book price: "); double price = scan.nextDouble(); inventory.add(new Book(id, title, price));
注意:原有逻辑中发现重复时执行的id--没有实际作用,既不会改变最终存入的图书ID,也无法阻止后续录入流程,可直接移除;原有Scanner读取书名的逻辑存在换行残留问题,连续调用next()、nextLine()会导致读取到的书名为空,需在读取数字类输入后先调用scan.nextLine()清空输入缓冲区的换行符,再读取字符串内容。
方案2:重写Book类的equals和hashCode方法(适合频繁使用列表方法判重的场景)
如果后续开发中需要频繁使用列表自带的contains方法做判重,可以在Book类中重写equals和hashCode方法,将图书ID作为判断两个Book实例是否相等的唯一依据:
// 写入Book类的重写方法 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Book target = (Book) o; return id == target.id; } @Override public int hashCode() { return Integer.hashCode(id); }
修改完成后,判重逻辑可以简化为:根据用户输入的ID构造一个临时Book对象(不需要填充title、price属性,因为相等判断只匹配ID),再调用inventory.contains(临时对象)即可快速判断库存中是否存在相同ID的图书。
内容的提问来源于stack exchange,提问作者CB89
相关产品推荐
相关产品推荐

