Dart sort List
last modified October 18, 2026
In this article we show how to sort List elements in Dart language.
Sorting
Sorting is arranging elements in an ordered sequence. In the past, several algorithms were developed to perform sorting on data, including merge sort, quick sort, selection sort, or bubble sort.
Shuffling, the opposite of sorting, is rearranging a sequence of elements in a random or meaningless order.
Data can be sorted alphabetically or numerically. The sort key specifies the criteria used to perform the sort. It is possible to sort objects by multiple keys. For instance, when sorting users, the names of the users could be used as primary sort key, and their occupation as the secondary sort key.
The List.sort method sorts the list in place; it modifies
the list and returns nothing. It does not work on fixed-size lists created with
const or List.unmodifiable. The sort is not guaranteed
to be stable: elements that compare as equal may change their relative order.
Dart sort List of integers
In the first example, we sort integers.
void main() {
final nums = <int>[2, 1, 8, 0, 4, 3, 5, 7, 9, 6];
nums.sort();
print(nums);
final reversed = nums.reversed;
print(reversed);
print(nums);
}
We have a list of integers. They are sorted and then reversed.
nums.sort();
The sort method sorts the integers in place. Without an argument,
the natural ordering is used.
final reversed = nums.reversed;
With reversed, we get a lazy iterable of the elements in reverse
order (printed in parentheses). The values in nums are not
changed. Call toList() to get a new list.
$ dart main.dart [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] (9, 8, 7, 6, 5, 4, 3, 2, 1, 0) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Dart sort List of strings
In the next example, we sort a list of strings.
void main() {
final words = <String>['sky', 'm', 'worm', 'cup', 'are', 'snail', 'water'];
words.sort();
print(words);
final reversed = words.reversed;
print(reversed);
print(words);
}
Strings are sorted alphabetically by default. The comparison is based on UTF-16 code units, so all upper-case letters come before lower-case ones.
$ dart main.dart [are, cup, m, sky, snail, water, worm] (worm, water, snail, sky, m, cup, are) [are, cup, m, sky, snail, water, worm]
Dart sort List case-insensitive
To ignore the case, we provide a comparison function that compares the
lower-cased strings. The compareTo method returns a negative
number, zero, or a positive number.
void main() {
final words = ['banana', 'Apple', 'cherry', 'apple', 'Banana'];
final copy = [...words]..sort();
print(copy);
words.sort((a, b) => a.toLowerCase().compareTo(b.toLowerCase()));
print(words);
}
The first sort puts the upper-case words first. The second sort ignores the case. Note that "Apple" and "apple" compare as equal in the second case, so their relative order is not guaranteed. We also created a copy of the list with the spread operator, which allows us to keep the original order.
$ dart main.dart [Apple, Banana, apple, banana, cherry] [Apple, apple, banana, Banana, cherry]
Dart List sort strings by length
The following example sorts the list of words by the words' length.
void main() {
final words = <String>[
'falcon', 'order', 'war', 'sky', 'ocean', 'blue',
'cloud', 'boy', 'by', 'raven', 'station', 'battalion'
];
words.sort((a, b) => a.length.compareTo(b.length));
print(words);
words.sort((a, b) => b.length.compareTo(a.length));
print(words);
}
We provide a custom comparison function to do the job. The list is printed in one line. Because the sort is not stable, the order of words with the same length may differ between Dart versions.
words.sort((a, b) => a.length.compareTo(b.length));
We provide an anonymous function to the sort method. This function
uses the compareTo method of the integer type to compare the two
values. The size of the words is returned with the length
property. Swapping the operands gives descending order.
$ dart main.dart [by, war, sky, boy, blue, order, ocean, cloud, raven, falcon, station, battalion] [battalion, station, falcon, order, ocean, cloud, raven, blue, war, sky, boy, by]
Dart sort List of objects
In the following example, we sort a list of Employee objects.
class Employee {
final String fname;
final String lname;
final int salary;
Employee(this.fname, this.lname, this.salary);
@override
String toString() => '$fname $lname: $salary';
}
void main() {
final empls = <Employee>[
Employee('John', 'Doe', 1230),
Employee('Adam', 'Novak', 670),
Employee('Robin', 'Brown', 2300),
Employee('Rowan', 'Cruise', 990),
Employee('Joe', 'Draker', 1190),
Employee('Janet', 'Doe', 980),
Employee('Lucy', 'Smith', 980),
Employee('Thomas', 'Moore', 1400),
];
empls.sort((a, b) => a.lname.compareTo(b.lname));
empls.forEach(print);
print('--------------------------');
empls.sort((a, b) => b.salary.compareTo(a.salary));
empls.forEach(print);
}
We have a list of employee objects. The employee has three attributes: first name, last name, and salary. We sort the list by employees' last names and then by their salary.
empls.sort((a, b) => a.lname.compareTo(b.lname));
The employees are sorted by their last names in ascending order.
empls.sort((a, b) => b.salary.compareTo(a.salary));
The employees are sorted by their salaries in descending order. There are ties (980 appears twice), and the sort is not stable, so the order of tied employees is arbitrary. In the next example we resolve ties with a second key.
$ dart main.dart Robin Brown: 2300 Rowan Cruise: 990 John Doe: 1230 Janet Doe: 980 Joe Draker: 1190 Thomas Moore: 1400 Adam Novak: 670 Lucy Smith: 980 -------------------------- Robin Brown: 2300 Thomas Moore: 1400 John Doe: 1230 Joe Draker: 1190 Rowan Cruise: 990 Janet Doe: 980 Lucy Smith: 980 Adam Novak: 670
Dart sort by multiple keys
To sort by several keys, we compare by the primary key first and use the
secondary key only when the primary keys are equal, that is, when
compareTo returns 0.
class Employee {
final String fname;
final String lname;
final int salary;
Employee(this.fname, this.lname, this.salary);
@override
String toString() => '$fname $lname: $salary';
}
void main() {
final empls = <Employee>[
Employee('John', 'Doe', 1230),
Employee('Adam', 'Novak', 670),
Employee('Robin', 'Brown', 2300),
Employee('Rowan', 'Cruise', 990),
Employee('Joe', 'Draker', 1190),
Employee('Janet', 'Doe', 980),
Employee('Lucy', 'Smith', 980),
Employee('Thomas', 'Moore', 1400),
];
empls.sort((a, b) {
final bySalary = b.salary.compareTo(a.salary);
if (bySalary != 0) return bySalary;
return a.lname.compareTo(b.lname);
});
empls.forEach(print);
}
The employees are ordered by salary in descending order, and employees with the same salary are ordered by their last names. The output is now deterministic.
$ dart main.dart Robin Brown: 2300 Thomas Moore: 1400 John Doe: 1230 Joe Draker: 1190 Rowan Cruise: 990 Janet Doe: 980 Lucy Smith: 980 Adam Novak: 670
Dart Comparable
If the object can be naturally sorted, we can use the Comparable
interface.
class Employee implements Comparable<Employee> {
final String fname;
final String lname;
final int salary;
Employee(this.fname, this.lname, this.salary);
@override
String toString() => '$fname $lname: $salary';
@override
int compareTo(Employee other) => lname.compareTo(other.lname);
}
void main() {
final empls = <Employee>[
Employee('John', 'Doe', 1230),
Employee('Adam', 'Novak', 670),
Employee('Robin', 'Brown', 2300),
Employee('Rowan', 'Cruise', 990),
Employee('Joe', 'Draker', 1190),
Employee('Janet', 'Doe', 980),
Employee('Lucy', 'Smith', 980),
Employee('Thomas', 'Moore', 1400),
];
empls.sort();
empls.forEach(print);
}
In the example, the Employee implements the Comparable
interface to have a default, natural ordering. Now sort can be
called without an argument.
@override int compareTo(Employee other) => lname.compareTo(other.lname);
We implement the compareTo method, which orders the employees by
their last names. John Doe and Janet Doe compare as equal, so their relative
order is not defined.
$ dart main.dart Robin Brown: 2300 Rowan Cruise: 990 John Doe: 1230 Janet Doe: 980 Joe Draker: 1190 Thomas Moore: 1400 Adam Novak: 670 Lucy Smith: 980
Dart sortedBy
The collection package provides extension methods that sort by a
key and return a new list without modifying the source: sorted,
sortedBy, and sortedByCompare. These methods are
stable.
$ dart pub add collection
import 'package:collection/collection.dart';
class Employee {
final String fname;
final String lname;
final int salary;
Employee(this.fname, this.lname, this.salary);
@override
String toString() => '$fname $lname: $salary';
}
void main() {
final empls = <Employee>[
Employee('John', 'Doe', 1230),
Employee('Adam', 'Novak', 670),
Employee('Robin', 'Brown', 2300),
Employee('Rowan', 'Cruise', 990),
Employee('Joe', 'Draker', 1190),
Employee('Janet', 'Doe', 980),
Employee('Lucy', 'Smith', 980),
Employee('Thomas', 'Moore', 1400),
];
final bySalary = empls.sortedBy<num>((e) => e.salary);
print(bySalary.first);
final byName = empls.sortedBy((e) => e.lname);
print(byName.map((e) => e.lname).toList());
print([3, 1, 2].sorted((a, b) => b.compareTo(a)));
}
The sortedBy method takes a function that extracts the sort key.
The original list is left untouched. The sorted method takes a
comparison function.
$ dart main.dart Adam Novak: 670 [Brown, Cruise, Doe, Doe, Draker, Moore, Novak, Smith] [3, 2, 1]
Dart shuffle
The opposite of sorting is shuffling. The shuffle method
rearranges the elements randomly; we can pass a seeded Random to
get a reproducible result.
import 'dart:math';
void main() {
final nums = [1, 2, 3, 4, 5, 6, 7, 8];
nums.shuffle(Random(1));
print(nums);
nums.sort();
print(nums);
}
We shuffle a list with a seeded generator and then sort it again.
$ dart main.dart [2, 3, 1, 7, 8, 6, 4, 5] [1, 2, 3, 4, 5, 6, 7, 8]
Source
Dart List.sort - API reference
In this article we have sorted Dart lists.
Author
List all Dart tutorials.