Comparable和Comparator的使用和细节
原创
©著作权归作者所有:来自51CTO博客作者l8947943s的原创作品,请联系作者获取转载授权,否则将追究法律责任
- 在日常的代码中,我们常常会用到排序,这时候就会用到Comparable和Comparator。
- 先使用Comparable进行举例:
定义ComparableUser 并实现Comparable接口
public class ComparableUser implements Comparable<ComparableUser> {
private int id;
private int age;
public ComparatorUser(){}
public ComparableUser(int id, int age) {
this.id = id;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "ComparableUser{" +
"id=" + id +
", age=" + age +
'}';
}
// 重写的是compareTo方法
@Override
public int compareTo(ComparableUser o) {
// 如果id相同,则按照age升序
if (this.id == o.id) {
return this.age - o.age;
}
// 否则按照id升序排列
return this.id - o.id;
}
}
进行测试:
public class ComparableTest {
public static void main(String[] args) {
ComparableUser[] user = new ComparableUser[] {
new ComparableUser(4, 18),
new ComparableUser(4, 15),
new ComparableUser(7, 12),
new ComparableUser(1, 13),
};
Arrays.sort(user);
for (int i = 0; i < user.length; i++) {
System.out.println(user[i].toString());
}
}
}
结果如图:
个人理解,Comparable是一个比较器,只是用来比较两个对象的区别(目前学习到这部分,应该还有其他的)。但是Comparable和目标类的耦合度太高,当需要调整算法,就得对原来的代码进行修改,这一点不符合设计模式的开闭原则。因此出现了Comparator接口
- 先使用Comparator进行举例:
定义ComparatorUser 并实现Comparator接口
public class ComparatorUser implements Comparator<ComparatorUser> {
private int id;
private int age;
public ComparatorUser(){}
public ComparatorUser(int id, int age) {
this.id = id;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "ComparableUser{" +
"id=" + id +
", age=" + age +
'}';
}
// 注意,重写了compare方法
@Override
public int compare(ComparatorUser o1, ComparatorUser o2) {
if (o1.id == o2.id) {
return o1.age - o2.age;
}
return o1.id - o2.id;
}
}
进行测试:
public class ComparatorTest {
public static void main(String[] args) {
ComparatorUser[] user = new ComparatorUser[] {
new ComparatorUser(4, 18),
new ComparatorUser(4, 15),
new ComparatorUser(7, 12),
new ComparatorUser(1, 13),
};
// 注意,有排序器的实现
Arrays.sort(user, new ComparatorUser());
for (int i = 0; i < user.length; i++) {
System.out.println(user[i].toString());
}
}
}
测试结果同上
注意:使用Comparator接口,重写的方法是compare方法。另外,在排序过程中,应该有对应的Comparator接口的实现,如:Arrays.sort(user, new ComparatorUser());
,否则报错找不到的调用规则
- 先使用Comparator进行改进:
为了减少代码的耦合,并方便修改,而不改变原来的代码,我们定义 ComparatorUser 类,并不再实现Comparator 方法
public class ComparatorUser {
private int id;
private int age;
public ComparatorUser(){}
public ComparatorUser(int id, int age) {
this.id = id;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "ComparableUser{" +
"id=" + id +
", age=" + age +
'}';
}
}
进行测试代码需要通过内部类的方式进行排序,如果变动只需要便内部类,不用修改原函数
public class ComparatorTest {
public static void main(String[] args) {
ComparatorUser[] user = new ComparatorUser[] {
new ComparatorUser(4, 18),
new ComparatorUser(4, 15),
new ComparatorUser(7, 12),
new ComparatorUser(1, 13),
};
// 通过内部类的方式实现排序规则
Arrays.sort(user, new Comparator<ComparatorUser>() {
@Override
public int compare(ComparatorUser o1, ComparatorUser o2) {
if (o1.getId() == o2.getId()) {
return o1.getAge() - o2.getAge();
}
return o1.getId() - o2.getId();
}
});
for (int i = 0; i < user.length; i++) {
System.out.println(user[i].toString());
}
}
}
使用lambda表达式进行简化
Arrays.sort(user, (o1, o2) -> {
if (o1.getId() == o2.getId()) {
return o1.getAge() - o2.getAge();
}
return o1.getId() - o2.getId();
}
);
- 总结
想要对象进行排序,推荐实现Comparable接口,并重写compareTo方法,通过Arrays.sort();传入排序对象即可
想要对对象及其以外且有可能变动代码的排序,推荐使用Comparator接口,并通过内部类是形式重写compare方法即可