主题
面试速答(先看这里)
**一句话结论:**Java.util包中的List接口继承了Collection接口,用来存放对象集合,所以对这些对象进行排序的时候,要么让对象类自己实现同类对象的比较,要么借助比较器进行比较排序。
60秒标准回答:
Java.util包中的List接口继承了Collection接口,用来存放对象集合,所以对这些对象进行排序的时候,要么让对象类自己实现同类对象的比较,要么借助比较器进行比较排序
举例:学生实体类,包含姓名和年龄属性,比较时先按姓名升序排序,如果姓名相同则按年龄升序排序
第一种:实体类自己实现Comparable接口比较
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **实现Comparable:**第一种:实体类自己实现Comparable接口比较
- **借助Comparator:**第二种:借助比较器进行排序。
- **通过Stream:**第三种:借助Stream进行排序,借助Stream的API,底层还是通过Comparable实现的。
- **有了Comparable为什么还需要Comparator?:**Comparable用于使某个类具备可排序能力。
- **compareTo和equals的使用场景有何区别?:**compareTo常用于排序和BigDecimal等数值的比较
**记忆锚点:**Set → Comparable → Comparator → compareTo → Stream → equals
加分表达:
- 举例:学生实体类,包含姓名和年龄属性,比较时先按姓名升序排序,如果姓名相同则按年龄升序排序。
- 也可以直接优化成: 通过Stream 第三种:借助Stream进行排序,借助Stream的API,底层还是通过Comparable实现的。
- 如上述代码中对不具备排序能力的Student进行排序 compareTo和equals的使用场景有何区别? compareTo常用于排序和BigDecimal等数值的比较 equals则是常用于业务语义中两个对象是否相同,如String常常通过equals来比较是否字面意义相同 既然Set是无序的,还怎么排序?
追问准备:
- 有了Comparable为什么还需要Comparator?
- Set真的是插入无序的吗?
典型回答
Java.util包中的List接口继承了Collection接口,用来存放对象集合,所以对这些对象进行排序的时候,要么让对象类自己实现同类对象的比较,要么借助比较器进行比较排序。
举例:学生实体类,包含姓名和年龄属性,比较时先按姓名升序排序,如果姓名相同则按年龄升序排序。
实现Comparable
第一种:实体类自己实现Comparable接口比较
java
public class Student implements Comparable<Student>{
private String name;
private int age;
@Override
public int compareTo(Student o) {
int flag = this.name.compareTo(o.name);
if(flag == 0) {
flag = this.age - o.age;
}
return flag;
}
}
Collections.sort(students);借助Comparator
第二种:借助比较器进行排序。
java
public class Student {
private String name;
private int age;
}
Collections.sort(students, (o1, o2) -> {
int flag = o1.getName().compareTo(o2.getName());
if(flag == 0) {
flag = o1.getAge() - o2.getAge();
}
return flag;
});也可以直接优化成:
java
Collections.sort(students, Comparator.comparing(Student::getName).thenComparingInt(Student::getAge));通过Stream
第三种:借助Stream进行排序,借助Stream的API,底层还是通过Comparable实现的。
java
public class Student {
private String name;
private int age;
}
// 如果Student实现了Comparable
students.stream().sorted().collect(Collectors.toList());
// 如果Student没有实现Comparable
students.stream().sorted((o1, o2) -> {
int flag = o1.getName().compareTo(o2.getName());
if(flag == 0) {
flag = o1.getAge() - o2.getAge();
}
return flag;
}).collect(Collectors.toList());知识扩展
有了Comparable为什么还需要Comparator?
Comparable用于使某个类具备可排序能力。如之前的Student类,实现该接口后覆盖其compareTo方法,即可具备可排序的能力。
但是仍然存在一些二方库的类没有实现Comparable,但是调用方也需要比较的,此时就需要使用Comparator接口。
Comparator是一个比较器接口,可以用来给不具备排序能力的对象进行排序。如上述代码中对不具备排序能力的Student进行排序
compareTo和equals的使用场景有何区别?
compareTo常用于排序和BigDecimal等数值的比较
equals则是常用于业务语义中两个对象是否相同,如String常常通过equals来比较是否字面意义相同
既然Set是无序的,还怎么排序?
这里说的是两个语境的不同,Set的无序,指的是插入顺序是无序的。虽然Set的插入顺序是无序的,Set也可以基于SortedSet要求对象实现Comparable来对Set中的元素进行排序。
Set真的是插入无序的吗?
并不是,Set有一个实现类是LinkedHashSet,它引用了LinkedHashMap,通过双向链表记录了每个node的插入顺序和查询顺序(可选),以此来达到Set的插入有序性。