Built-in Sorting in C++, Java, JavaScript & Python
In real code you should almost always call the standard library sort, not hand-roll one — they are decades-tuned hybrids (introsort, Timsort) that outperform anything you’ll write. The catch is that each language’s API has its own conventions and one famous trap. This page shows the idioms for sorting, sorting with a custom order, and sorting by a key in all four languages.
Sorting ascending — the basics
The default sort puts elements in ascending (natural) order.
#include <algorithm>
#include <vector>
std::vector<int> v = {3, 1, 2};
std::sort(v.begin(), v.end()); // {1, 2, 3}
std::sort(v.begin(), v.end(), std::greater<int>()); // {3, 2, 1} descending
import java.util.Arrays;
import java.util.Collections;
int[] prim = {3, 1, 2};
Arrays.sort(prim); // {1, 2, 3} (primitives)
Integer[] boxed = {3, 1, 2};
Arrays.sort(boxed, Collections.reverseOrder()); // {3, 2, 1} descending
const v = [3, 1, 2];
v.sort((a, b) => a - b); // [1, 2, 3] ascending
v.sort((a, b) => b - a); // [3, 2, 1] descending
v = [3, 1, 2]
v.sort() # in place -> [1, 2, 3]
ordered = sorted(v, reverse=True) # new list -> [3, 2, 1]
The JavaScript gotcha:
Array.prototype.sort()with no comparator converts every element to a string and sorts lexicographically. So[10, 2, 1].sort()returns[1, 10, 2], not[1, 2, 10]— because"10" < "2"as strings. Always pass a comparator for numbers:arr.sort((a, b) => a - b). This is one of the most common JavaScript bugs.
In place vs returning a new array
| Language | In place | Returns a new sorted copy |
|---|---|---|
| C++ | std::sort(v.begin(), v.end()) | auto c = v; std::sort(c.begin(), c.end()); |
| Java | Arrays.sort(a) / Collections.sort(list) | list.stream().sorted().toList() |
| JavaScript | arr.sort(cmp) (also mutates!) | [...arr].sort(cmp) or arr.toSorted(cmp) |
| Python | list.sort() | sorted(iterable) |
Gotcha: JavaScript’s
sortmutates the array and returns it —const b = a.sort()leavesasorted too. Usearr.toSorted(cmp)(ES2023) or[...arr].sort(cmp)for a non-destructive sort.
Sorting by a key (the most useful skill)
To sort objects by a field — or numbers by a derived value — give the sort a key/comparator. Below: sort words by length, shortest first.
#include <algorithm>
#include <string>
#include <vector>
std::vector<std::string> w = {"bbb", "a", "cc"};
std::sort(w.begin(), w.end(),
[](const std::string& x, const std::string& y) {
return x.size() < y.size(); // compare by length
});
// {"a", "cc", "bbb"}
import java.util.Arrays;
import java.util.Comparator;
String[] w = {"bbb", "a", "cc"};
Arrays.sort(w, Comparator.comparingInt(String::length)); // by length
// {"a", "cc", "bbb"}
const w = ["bbb", "a", "cc"];
w.sort((x, y) => x.length - y.length); // by length
// ["a", "cc", "bbb"]
w = ["bbb", "a", "cc"]
w.sort(key=len) # by length
# ["a", "cc", "bbb"]
For beginners: Python’s
key=is the cleanest model — you give a function that maps each element to the value to sort by, and Python compares those values. It computes each key once (the “decorate-sort-undecorate” pattern), so it’s also efficient.
Multi-key sorting (ties)
Sort by one field, breaking ties with another — e.g. by age ascending, then name ascending.
struct Person { std::string name; int age; };
std::vector<Person> p = /* ... */;
std::sort(p.begin(), p.end(), [](const Person& a, const Person& b) {
if (a.age != b.age) return a.age < b.age;
return a.name < b.name; // tie-breaker
});
record Person(String name, int age) {}
people.sort(Comparator.comparingInt(Person::age)
.thenComparing(Person::name)); // tie-breaker
people.sort((a, b) => a.age - b.age || a.name.localeCompare(b.name));
// `|| ...` is the tie-breaker when ages are equal (a.age - b.age === 0)
# Python's sort is stable, so sort by the secondary key first,
# then by the primary — or use a tuple key in one pass:
people.sort(key=lambda p: (p.age, p.name)) # by age, then name
Stability of the built-ins
Stability (equal elements keep their input order) matters for multi-key sorting. As covered on the comparison page:
- Python
sorted/sort— stable (Timsort). - JavaScript
sort— stable since ES2019. - Java —
Arrays.sorton objects andCollections.sortare stable (Timsort); on primitives it is not stable (dual-pivot quick sort) — but for primitives stability is meaningless since equal ints are indistinguishable. - C++
std::sortis not stable; usestd::stable_sortwhen you need it.
Going deeper: Comparators must define a strict weak ordering — consistent and transitive. A broken comparator (e.g. returning
truefor bothcmp(a,b)andcmp(b,a)) is undefined behavior in C++ and throws “Comparison method violates its general contract!” in Java. For numbers,a - bworks but can overflow for large ints in C++/Java — preferInteger.compare(a, b)/(a > b) - (a < b)there.
That’s the practical toolkit. Now lock it in with the sorting exercises.