使用 Comparator 和 Comparable 对集合排序:如何轻松排序 Java 集合?
全文目录:
- 开篇语
- 前言
- 1. `Comparable` 接口
- 1.1. `Comparable` 接口的定义
- 1.2. `Comparable` 排序示例
- 输出:
- 2. `Comparator` 接口
- 2.1. `Comparator` 接口的定义
- 2.2. `Comparator` 排序示例
- 输出:
- 2.3. `Comparator` 使用 lambda 表达式
- 输出:
- 2.4. 多种排序方式的组合
- 输出:
- 3. `Comparable` 和 `Comparator` 的比较
- 4. 总结
- 文末
开篇语
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
在 Java 中,排序是我们常常会遇到的操作。幸运的是,Java 提供了两种非常常用的方式来对集合进行排序:Comparable
和 Comparator
。它们分别适用于不同的排序需求,并且各有其特点和使用场景。今天,我们将深入分析这两种排序机制,并通过代码示例帮助你理解如何灵活地对集合进行排序。
1. Comparable
接口
Comparable
接口是 Java 自带的用于对对象进行排序的机制。它允许对象按照自然顺序进行排序,通常用于当你希望一个类的实例对象在没有外部干预的情况下就能比较大小的情况。
1.1. Comparable
接口的定义
Comparable
接口只有一个方法 compareTo()
,它定义了当前对象与传入对象的比较规则。
public interface Comparable<T> {int compareTo(T o);
}
- 返回值:
- 负数:当前对象小于传入对象
- 零:当前对象等于传入对象
- 正数:当前对象大于传入对象
1.2. Comparable
排序示例
假设我们有一个 Person
类,其中包含 name
和 age
两个属性,我们希望按照 age
从小到大进行排序。我们可以实现 Comparable
接口,并重写 compareTo()
方法。
import java.util.*;class Person implements Comparable<Person> {String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}// 实现 compareTo 方法,按 age 排序@Overridepublic int compareTo(Person other) {return Integer.compare(this.age, other.age);}@Overridepublic String toString() {return name + ": " + age;}
}public class ComparableExample {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));// 使用 Collections.sort 对集合进行排序Collections.sort(people);// 打印排序后的结果for (Person person : people) {System.out.println(person);}}
}
输出:
Bob: 25
Alice: 30
Charlie: 35
在上面的代码中,Person
类实现了 Comparable
接口,重写了 compareTo()
方法,按照 age
进行排序。当我们调用 Collections.sort()
方法时,集合就会按照 compareTo()
方法的逻辑进行排序。
2. Comparator
接口
Comparator
接口是 Java 提供的另一种排序机制,与 Comparable
不同,它并不改变对象本身,而是提供一个外部的比较器来定义排序规则。使用 Comparator
,你可以在不修改对象类的情况下灵活地实现多种排序方式。
2.1. Comparator
接口的定义
Comparator
接口有两个重要的方法:
public interface Comparator<T> {int compare(T o1, T o2);
}
- 返回值:
- 负数:
o1
小于o2
- 零:
o1
等于o2
- 正数:
o1
大于o2
- 负数:
2.2. Comparator
排序示例
如果我们希望对 Person
类按 name
字母顺序进行排序,而不影响按 age
排序的逻辑,我们可以使用 Comparator
。
import java.util.*;class Person {String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return name + ": " + age;}
}public class ComparatorExample {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));// 使用 Comparator 按 name 排序people.sort(new Comparator<Person>() {@Overridepublic int compare(Person p1, Person p2) {return p1.name.compareTo(p2.name);}});// 打印排序后的结果for (Person person : people) {System.out.println(person);}}
}
输出:
Alice: 30
Bob: 25
Charlie: 35
在这个例子中,我们没有修改 Person
类,而是创建了一个匿名 Comparator
类,在 compare()
方法中定义了按 name
排序的逻辑。使用 people.sort()
方法对列表进行了排序。
2.3. Comparator
使用 lambda 表达式
从 Java 8 开始,我们可以使用更简洁的方式来实现 Comparator
,即通过 lambda 表达式。这样可以让代码更加简洁,减少冗余。
import java.util.*;class Person {String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return name + ": " + age;}
}public class ComparatorLambdaExample {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 35));// 使用 lambda 表达式按 name 排序people.sort((p1, p2) -> p1.name.compareTo(p2.name));// 打印排序后的结果for (Person person : people) {System.out.println(person);}}
}
输出:
Alice: 30
Bob: 25
Charlie: 35
通过 lambda 表达式,我们可以轻松实现按 name
排序,并且代码更加简洁。
2.4. 多种排序方式的组合
如果我们希望根据多个属性进行排序(例如先按 age
排序,如果 age
相同,再按 name
排序),可以使用 Comparator
的 thenComparing()
方法来组合多个排序条件。
import java.util.*;class Person {String name;int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return name + ": " + age;}
}public class MultiComparatorExample {public static void main(String[] args) {List<Person> people = new ArrayList<>();people.add(new Person("Alice", 30));people.add(new Person("Bob", 25));people.add(new Person("Charlie", 30));people.add(new Person("Dave", 25));// 按 age 排序,如果 age 相同,再按 name 排序people.sort(Comparator.comparingInt(Person::getAge).thenComparing(Person::getName));// 打印排序后的结果for (Person person : people) {System.out.println(person);}}
}
输出:
Bob: 25
Dave: 25
Alice: 30
Charlie: 30
通过 Comparator.comparingInt()
和 thenComparing()
方法,我们实现了先按 age
排序,再按 name
排序的功能。
3. Comparable
和 Comparator
的比较
特性 | Comparable | Comparator |
---|---|---|
排序方式 | 自然排序(类内部实现) | 外部比较器定义(灵活自定义排序规则) |
实现的接口方法 | compareTo() | compare() |
修改对象类 | 需要修改对象类 | 无需修改对象类 |
使用场景 | 类本身有天然的排序顺序时 | 需要多种排序规则或对象类无法修改时 |
4. 总结
Comparable
:适用于类本身已经有了自然排序顺序的情况,且仅需要一种排序方式。通过实现compareTo()
方法,我们可以定义类的默认排序规则。Comparator
:适用于需要多种排序方式的场景,或者当我们不能修改原始类时。通过compare()
方法,可以定义任意排序逻辑,甚至可以组合多个比较器进行复合排序。
在实际开发中,我们可以根据具体需求灵活选择使用 Comparable
还是 Comparator
,并通过 Java 8 引入的 lambda 表达式来简化代码。
… …
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
… …
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!