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 教程。