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.
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.
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.
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.
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.
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
- Consistency: Ensure compareTo is consistent with equals.
- Transitivity: Maintain a < b & b < c ⇒ a < c.
- Null Safety: Handle null values if needed.
- Performance: Keep comparisons efficient for sorting.
Source
This tutorial covered Dart's Comparable interface with practical examples demonstrating object comparison and sorting.
Author
List all Dart tutorials.