Comparable
和 Comparator
经常弄混,升序降序到底该怎么实现经常搞反了??
由于当时学这两个的时候没学扎实,后边写算法的时候经常被这俩搞的头疼。
所以决定写一篇博客详解一波,一劳永逸!!!
目录
前言
1. Comparable 接口
实现 Comparable 接口
使用 Lambda 表达式实现 Comparable 接口
2. Comparator 接口
使用匿名内部类实现 Comparator 接口
使用 Lambda 表达式实现 Comparator 接口
记忆升序降序的技巧
总结
他们都是用于对象排序的接口。虽然这两个接口有相似的功能,但它们在使用场景和实现方式上有些不同。这里将详细讲解
Comparable
和Comparator
,并通过匿名内部类和 Lambda 表达式的方式提供示例代码讲解。
Comparable
接口Comparable
接口是一个用于定义对象的自然排序规则的接口。它有一个方法:
int compareTo(T o);
该方法返回一个整数,表示当前对象与指定对象的顺序关系:
- 如果当前对象小于指定对象,返回负整数。
- 如果当前对象等于指定对象,返回零。
- 如果当前对象大于指定对象,返回正整数。
Comparable
接口假设我们有一个 Person
类,我们需要根据 age
字段对 Person
对象进行排序。首先,我们使用匿名内部类来实现 Comparable
接口。
import java.util.*;
class Person implements Comparable {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
// 按照年龄升序排序
return Integer.compare(this.age, other.age);
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
public static void main(String[] args) {
List people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
);
// 使用匿名内部类实现排序
Collections.sort(people);
// 打印排序后的结果
System.out.println(people);
}
}
结果:
[Person{name='Bob', age=25}, Person{name='Alice', age=30}, Person{name='Charlie', age=35}]
解释:
Person
类实现了Comparable
接口,重写了compareTo
方法,根据age
排序。main
方法创建了一个List
,然后使用Collections.sort
来对列表进行排序。
Comparable
接口Java 8 引入了 Lambda 表达式,它可以让代码更加简洁。在上面的示例中,我们可以使用 Lambda 表达式替代匿名内部类。
import java.util.*;
class Person implements Comparable {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person other) {
return Integer.compare(this.age, other.age);
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
public static void main(String[] args) {
List people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
);
// 使用 Lambda 表达式实现排序
Collections.sort(people, (p1, p2) -> p1.name.compareTo(p2.name));
// 打印排序后的结果
System.out.println(people);
}
}
解释:
Collections.sort
方法的第二个参数是一个Comparator
,在这里使用了 Lambda 表达式(p1, p2) -> p1.name.compareTo(p2.name)
来进行字符串按字母顺序排序。- 相较于匿名内部类,Lambda 表达式更加简洁,代码更易于理解。
Comparator
接口Comparator
接口用于定义不同的排序规则,它的作用是提供一种灵活的方式来排序对象。Comparator
有多个重载方法,但最常用的是:
int compare(T o1, T o2);
与 Comparable
的 compareTo
不同,Comparator
是外部提供的排序规则,它可以与多个排序条件同时使用。
Comparator
接口我们仍然使用 Person
类,但这次我们使用 Comparator
来按年龄排序,并演示如何使用匿名内部类。
import java.util.*;
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
public static void main(String[] args) {
List people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
);
// 使用匿名内部类创建 Comparator
Collections.sort(people, new Comparator() {
@Override
public int compare(Person p1, Person p2) {
// 按照年龄升序排序
return Integer.compare(p1.age, p2.age);
}
});
// 打印排序后的结果
System.out.println(people);
}
}
解释:
Collections.sort
方法接受一个Comparator
,在这里使用匿名内部类来实现按age
排序的逻辑。- 匿名内部类中的
compare
方法定义了两个Person
对象的比较逻辑:通过Integer.compare(p1.age, p2.age)
对年龄进行升序排序。
Comparator
接口同样的例子,我们可以使用 Lambda 表达式简化 Comparator
的实现。
import java.util.*;
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
public static void main(String[] args) {
List people = Arrays.asList(
new Person("Alice", 30),
new Person("Bob", 25),
new Person("Charlie", 35)
);
// 使用 Lambda 表达式创建 Comparator
Collections.sort(people, (p1, p2) -> Integer.compare(p1.age, p2.age));
// 打印排序后的结果
System.out.println(people);
}
}
解释:
Collections.sort
的第二个参数是一个Comparator
,这里使用 Lambda 表达式(p1, p2) -> Integer.compare(p1.age, p2.age)
来按age
排序。- Lambda 表达式更加简洁,省去了匿名内部类的冗余代码。
不要用大于小于号来比较,直接做 减法或者 compare,顺着写升序,反着写降序!!
// 使用 Lambda 表达式创建 Comparator
Collections.sort(people, (p1, p2) -> Integer.compare(p1.age, p2.age));
Collections.sort(people, (p1, p2) -> p1.age - p2.age);
// o1,o2,这种 1 2 的顺序就是升序,小的在前
Collections.sort(people, (p1, p2) -> Integer.compare(p2.age, p1.age));
Collections.sort(people, (p1, p2) -> p2.age - p1.age);
//同理 o2,o1,这种 2 1 的顺序就是降序序,大的在前
Comparable
:用于定义对象的自然排序规则,必须在类内部实现。通过实现compareTo
方法来指定排序逻辑。Comparator
:用于在外部定义排序规则,能够灵活地实现多种排序方式。它是一个函数式接口,可以通过匿名内部类或 Lambda 表达式来实现。
秘诀 : 顺着写升序,反着写降序!!!