Sorting & Searching
Sorting in real apps
You sort constantly: a feed by date, contacts by name, products by price. The good news — you almost never write a sorting algorithm by hand. Every platform’s built-in sort is a highly optimised O(n log n) algorithm (Timsort/introsort). Your job is to call it correctly and supply the right comparison.
val byNewest = posts.sortedByDescending { it.createdAt }
val byName = users.sortedBy { it.name.lowercase() }
// multi-key: by city, then by name
val sorted = users.sortedWith(compareBy({ it.city }, { it.name }))
Know the complexity
- Good sorts (the built-ins) — O(n log n).
- Naive sorts (bubble/insertion) — O(n²), only for tiny or nearly-sorted data.
- Sorting is not free — sorting a large list on the main thread can drop frames. Sort off-thread, or keep data sorted as it arrives.
A note on stable sorts
A stable sort keeps equal items in their original order — important when you sort by one field but want to preserve a previous ordering for ties. The built-in sorts on mobile are stable, which is what you usually want.
Searching: linear vs binary
Linear search scans every item — O(n). Fine for small lists, but wasteful for large ones.
val found = items.firstOrNull { it.id == target } // O(n)
Binary search is O(log n) but requires the data to be sorted. It repeatedly halves the search range — 1,000 items take ~10 steps, a million take ~20.
// list must be sorted by the same key
val index = sortedList.binarySearch { it.id.compareTo(target) }
When to use what (mobile)
- Need a one-off lookup by key? A hash map (O(1)) usually beats sorting + binary search.
- Need sorted order for display AND fast lookup? Keep it sorted and binary-search.
- Small list? Linear search is perfectly fine — don’t over-engineer.
Practical tips
- Don’t re-sort the same list every time the UI rebuilds — sort once and cache.
- Compute sort keys cheaply (don’t do heavy work inside the comparator, which runs many times).
- For huge datasets, sort/search on a background thread or let your database (which is optimised and indexed) do it.
Common mistakes
- Binary searching an unsorted list (wrong results).
- Sorting large lists on the main thread (jank).
- Re-sorting on every recomposition/redraw instead of caching.
- Heavy work inside a comparator (it’s called O(n log n) times).
Summary: Use built-in O(n log n) stable sorts with the right comparator, and sort off the main thread for big data. Linear search is O(n); binary search is O(log n) but needs sorted data; a hash map’s O(1) lookup often beats both. Sort once, cache, and let the database sort large sets.