ZetCode

Dart Comparable Interface

last modified June 4, 2025

The Comparable interface in Dart defines how objects should be compared. It enables natural ordering of objects and is used by sorting algorithms.

Classes implementing Comparable must define the compareTo method. This method returns negative, zero, or positive values based on object ordering.

Basic Comparable Implementation

Here's a simple example implementing Comparable for a Person class.

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);
}

The Person class implements Comparable<Person> and compares by age. The compareTo method returns the age difference. Sorting uses this natural order.

$ dart main.dart
[Bob (25), Alice (30), Charlie (35)]

Comparing Multiple Properties

We can implement more complex comparison logic using multiple properties.

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);
}

Products are first sorted by rating (descending), then by price (ascending). The compareTo method implements this multi-level comparison logic.

$ dart main.dart
[Phone ($699.99, 5 stars), Tablet ($499.99, 4 stars), Laptop ($999.99, 4 stars)]

String Comparison

String already implements Comparable, but we can customize the comparison.

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);
}

This implements case-insensitive title comparison for books. The built-in String compareTo is used after converting to lowercase.

$ dart main.dart
[1984 by George Orwell, animal farm by George Orwell, Dune by Frank Herbert]

Reverse Order Comparison

We can implement reverse ordering by inverting the comparison result.

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);
}

Tasks are sorted by due date in descending order (newest first). We reverse the comparison by comparing other.dueDate to this.dueDate.

$ dart main.dart
[Write report (due 2025-04-07), Call client (due 2025-04-05), Buy groceries (due 2025-04-04)]

Using Comparable with Collections

Comparable enables useful operations on collections like min, max, and 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');
}

The Student class enables collection operations through Comparable. reduce finds min/max, and binarySearch quickly locates items in sorted lists.

$ dart main.dart
Lowest GPA: Bob (GPA: 3.2)
Highest GPA: Charlie (GPA: 3.9)
Alice is at index 1

Best Practices

Source

Dart Comparable Documentation

This tutorial covered Dart's Comparable interface with practical examples demonstrating object comparison and sorting.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Dart tutorials.