ZetCode

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

最佳实践

来源

Dart Comparable 文档

本教程通过实际示例涵盖了 Dart 的 Comparable 接口,演示了对象比较和排序。

作者

我的名字是 Jan Bodnar,我是一名热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在教授编程方面拥有超过十年的经验。

列出 所有 Dart 教程