Dart Comparable 接口
最后修改日期:2025 年 6 月 4 日
Dart 中的 Comparable 接口定义了对象应该如何进行比较。它实现了对象的自然排序,并被排序算法使用。
实现 Comparable 的类必须定义 compareTo 方法。该方法根据对象顺序返回负值、零或正值。
基本的 Comparable 实现
这是一个为 Person 类实现 Comparable 的简单示例。
main.dart
class Person implements Comparable<Person> {
final String name;
final int age;
Person(this.name, this.age);
@override
int compareTo(Person other) {
return age - other.age;
}
@override
String toString() => '$name ($age)';
}
void main() {
var people = [
Person('Alice', 30),
Person('Bob', 25),
Person('Charlie', 35)
];
people.sort();
print(people);
}
Person 类实现了 Comparable<Person> 并按年龄进行比较。compareTo 方法返回年龄差。排序使用这种自然顺序。
$ dart main.dart [Bob (25), Alice (30), Charlie (35)]
比较多个属性
我们可以实现更复杂的比较逻辑,使用多个属性。
main.dart
class Product implements Comparable<Product> {
final String name;
final double price;
final int rating;
Product(this.name, this.price, this.rating);
@override
int compareTo(Product other) {
if (rating != other.rating) {
return other.rating - rating; // Higher rating first
}
return price.compareTo(other.price); // Then lower price
}
@override
String toString() => '$name (\$$price, $rating stars)';
}
void main() {
var products = [
Product('Laptop', 999.99, 4),
Product('Phone', 699.99, 5),
Product('Tablet', 499.99, 4)
];
products.sort();
print(products);
}
产品首先按评分(降序)排序,然后按价格(升序)排序。compareTo 方法实现了这种多级比较逻辑。
$ dart main.dart [Phone ($699.99, 5 stars), Tablet ($499.99, 4 stars), Laptop ($999.99, 4 stars)]
字符串比较
String 已经实现了 Comparable,但我们可以自定义比较。
main.dart
class Book implements Comparable<Book> {
final String title;
final String author;
Book(this.title, this.author);
@override
int compareTo(Book other) {
// Case-insensitive comparison
return title.toLowerCase().compareTo(other.title.toLowerCase());
}
@override
String toString() => '$title by $author';
}
void main() {
var books = [
Book('Dune', 'Frank Herbert'),
Book('1984', 'George Orwell'),
Book('animal farm', 'George Orwell')
];
books.sort();
print(books);
}
这实现了对书籍不区分大小写的标题比较。在转换为小写后,使用内置的 String compareTo。
$ dart main.dart [1984 by George Orwell, animal farm by George Orwell, Dune by Frank Herbert]
反向排序比较
我们可以通过反转比较结果来实现反向排序。
main.dart
class Task implements Comparable<Task> {
final String description;
final DateTime dueDate;
Task(this.description, this.dueDate);
@override
int compareTo(Task other) {
// Sort by due date in reverse (newest first)
return other.dueDate.compareTo(dueDate);
}
@override
String toString() => '$description (due ${dueDate.toLocalDate()})';
}
void main() {
var now = DateTime.now();
var tasks = [
Task('Write report', now.add(Duration(days: 3))),
Task('Buy groceries', now),
Task('Call client', now.add(Duration(days: 1)))
];
tasks.sort();
print(tasks);
}
任务按到期日期降序排序(最新的在前)。我们通过比较 other.dueDate 和 this.dueDate 来反转比较。
$ dart main.dart [Write report (due 2025-04-07), Call client (due 2025-04-05), Buy groceries (due 2025-04-04)]
将 Comparable 与集合一起使用
Comparable 允许在集合上进行有用的操作,例如 min、max 和 binarySearch。
main.dart
class Student implements Comparable<Student> {
final String name;
final double gpa;
Student(this.name, this.gpa);
@override
int compareTo(Student other) => gpa.compareTo(other.gpa);
@override
String toString() => '$name (GPA: $gpa)';
}
void main() {
var students = [
Student('Alice', 3.7),
Student('Bob', 3.2),
Student('Charlie', 3.9)
];
// Find min and max
print('Lowest GPA: ${students.reduce((a, b) => a.compareTo(b) < 0 ? a : b)}');
print('Highest GPA: ${students.reduce((a, b) => a.compareTo(b) > 0 ? a : b)}');
// Binary search requires sorted list
students.sort();
var index = students.binarySearch(Student('', 3.7));
print('Alice is at index $index');
}
Student 类通过 Comparable 实现了集合操作。reduce 用于查找 min/max,binarySearch 则可以快速定位排序列表中的项。
$ dart main.dart Lowest GPA: Bob (GPA: 3.2) Highest GPA: Charlie (GPA: 3.9) Alice is at index 1
最佳实践
- 一致性:确保 compareTo 与 equals 一致。
- 传递性:保持 a < b 且 b < c ⇒ a < c。
- Null 安全:如果需要,处理 null 值。
- 性能:保持比较的高效性以用于排序。
来源
本教程通过实际示例涵盖了 Dart 的 Comparable 接口,演示了对象比较和排序。
作者
列出 所有 Dart 教程。