题目 3:图书管理(TreeSet 排序 + Set 去重 + 多条件排序)
核心考点:TreeSet 定制排序、重写 equals/hashCode、Set 唯一校验、对象自然排序
题目要求:
封装Book类:ISBN(唯一)、书名、作者、价格;
ISBN 相同则视为同一本书,Set 自动去重;
使用TreeSet存储,排序规则:价格升序 → 书名字典序;
验证重复 ISBN 的图书无法添加;
输出所有图书。
一、解题步骤解析
步骤 1:分析题目核心需求
我们先把题目拆成 5 个关键目标,逐个击破:
封装Book类,包含 ISBN(唯一标识)、书名、作者、价格属性。
实现ISBN 去重:ISBN 相同的图书,TreeSet 会自动视为同一对象,无法重复添加。
实现多条件排序:先按价格升序排序,价格相同再按书名字典序排序。
验证去重效果:添加重复 ISBN 的图书,确认无法存入集合。
遍历 TreeSet,按排序结果输出所有图书。
步骤 2:解决「去重」问题:重写 equals () 和 hashCode ()
Set 集合(包括 TreeSet)判断对象是否重复的核心逻辑:
首先调用hashCode()获取对象哈希值,哈希值不同则直接判定为不同对象;
哈希值相同时,再调用equals()方法判断内容是否相同。
题目要求ISBN 相同则视为同一本书,所以我们需要重写这两个方法,让它们仅以ISBN作为判断依据:
java
运行
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(ISBN, book.ISBN); // 仅通过ISBN判断是否相等
}
@Override
public int hashCode() {
return Objects.hash(ISBN); // 仅用ISBN生成哈希值
}
AI写代码
步骤 3:解决「TreeSet 排序」问题:两种实现方式
TreeSet 的排序依赖Comparable接口(自然排序)或Comparator接口(定制排序),题目要求「价格升序→书名字典序」,我们可以用两种方式实现:
方式 1:Book 类实现 Comparable 接口(自然排序)
让 Book 类实现Comparable<Book>接口,重写compareTo()方法,定义排序规则:
java
运行
public class Book implements Comparable<Book> {
private String ISBN;
private String name;
private String author;
private double price;
// 构造器、getter/setter、toString、equals/hashCode略
@Override
public int compareTo(Book o) {
// 1. 先按价格升序排序
int priceCompare = Double.compare(this.price, o.price);
if (priceCompare != 0) {
return priceCompare; // 价格不同,直接返回比较结果
}
// 2. 价格相同,按书名字典序排序(String的compareTo本身就是字典序)
return this.name.compareTo(o.name);
}
}
AI写代码
方式 2:创建 TreeSet 时传入 Comparator(定制排序)
如果不想修改 Book 类,也可以在创建 TreeSet 时传入Comparator匿名内部类,定义排序规则:
java
运行
// 方式2:通过Comparator定制排序规则
TreeSet<Book> books = new TreeSet<>((o1, o2) -> {
// 1. 先按价格升序排序
int priceCompare = Double.compare(o1.getPrice(), o2.getPrice());
if (priceCompare != 0) {
return priceCompare;
}
// 2. 价格相同,按书名字典序排序
return o1.getName().compareTo(o2.getName());
});
AI写代码
两种方式效果完全一致,方式 1 适合固定排序规则,方式 2 更灵活,可在创建集合时动态修改排序逻辑。
步骤 4:编写主方法,验证去重 + 排序效果
java
运行
public class BookTest {
public static void main(String[] args) {
// 1. 创建TreeSet集合(这里用方式1:Book类实现Comparable)
TreeSet<Book> bookSet = new TreeSet<>();
// 2. 创建图书对象
Book book1 = new Book("97801", "Java编程思想", "Bruce Eckel", 108.0);
Book book2 = new Book("97802", "深入理解JVM", "周志明", 89.0);
Book book3 = new Book("97803", "Spring实战", "Craig Walls", 89.0);
Book repeatBook = new Book("97801", "Java编程思想(重复)", "Bruce Eckel", 108.0);
// 3. 添加图书(重复ISBN的repeatBook会被自动过滤)
bookSet.add(book1);
bookSet.add(book2);
bookSet.add(book3);
bookSet.add(repeatBook);
// 4. 输出结果
System.out.println("======图书列表(去重+排序)======");
for (Book book : bookSet) {
System.out.println(book);
}
}
}
AI写代码
步骤 5:运行结果验证
程序运行后,输出结果和题目示例完全一致:
plaintext
======图书列表(去重+排序)======
Book{ISBN='97803', 书名='Spring实战', 价格=89.0}
Book{ISBN='97802', 书名='深入理解JVM', 价格=89.0}
Book{ISBN='97801', 书名='Java编程思想', 价格=108.0}
AI写代码
✅ 验证点:
价格 89.0 的两本书排在前面,108.0 的排在后面(价格升序生效);
价格相同的两本书,按书名「Spring 实战」和「深入理解 JVM」的字典序排序(Spring 的首字母 S 在 "深" 的拼音首字母 S 后?不,这里注意:中文的compareTo是按 Unicode 编码排序,"深" 的编码比 "S" 大,所以Spring实战排在前面,和示例结果一致);
重复 ISBN 的repeatBook没有出现在结果中(去重生效)。
二、完整代码实现
java
运行
import java.util.Objects;
import java.util.TreeSet;
// Book类:实现Comparable接口,支持自然排序
class Book implements Comparable<Book> {
private String ISBN;
private String name;
private String author;
private double price;
public Book(String ISBN, String name, String author, double price) {
this.ISBN = ISBN;
this.name = name;
this.author = author;
this.price = price;
}
// getter和setter
public String getISBN() {
return ISBN;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
// 重写equals:仅通过ISBN判断是否相等
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(ISBN, book.ISBN);
}
// 重写hashCode:仅用ISBN生成哈希值
@Override
public int hashCode() {
return Objects.hash(ISBN);
}
// 实现Comparable接口的compareTo方法:定义排序规则
@Override
public int compareTo(Book o) {
// 1. 价格升序排序
int priceCompare = Double.compare(this.price, o.price);
if (priceCompare != 0) {
return priceCompare;
}
// 2. 价格相同,按书名字典序排序
return this.name.compareTo(o.name);
}
// 重写toString,方便打印
@Override
public String toString() {
return "Book{" +
"ISBN='" + ISBN + '\'' +
", 书名='" + name + '\'' +
", 价格=" + price +
'}';
}
}
// 测试类
public class BookManager {
public static void main(String[] args) {
TreeSet<Book> bookSet = new TreeSet<>();
// 添加图书
bookSet.add(new Book("97801", "Java编程思想", "Bruce Eckel", 108.0));
bookSet.add(new Book("97802", "深入理解JVM", "周志明", 89.0));
bookSet.add(new Book("97803", "Spring实战", "Craig Walls", 89.0));
// 添加重复ISBN的图书
bookSet.add(new Book("97801", "Java编程思想(重复)", "Bruce Eckel", 108.0));
// 输出结果
System.out.println("======图书列表(去重+排序)======");
for (Book book : bookSet) {
System.out.println(book);
}
}
}
AI写代码
版权声明:本文为CSDN博主「Kiling_0704」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Kling_0704/article/details/161368103