← Назад к вопросам

Как работает sortBy в Kotlin?

1.0 Junior🔥 101 комментариев
#Kotlin основы#Коллекции и структуры данных

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как работает sortBy в Kotlin

sortBy — это функция расширения (extension function) для изменяемых коллекций (MutableList, MutableCollection), которая выполняет сортировку на месте (in-place sort), то есть изменяет исходную коллекцию. Она принимает селектор (selector) — лямбда-функцию, которая возвращает ключ сортировки для каждого элемента.

Принцип работы

  1. Определение ключей: Для каждого элемента коллекции вычисляется ключ с помощью функции-селектора.
  2. Сравнение ключей: Элементы сортируются по естественному порядку (natural order) вычисленных ключей. Это означает, что ключи должны реализовывать интерфейс Comparable<T>.
  3. Изменение исходной коллекции: Используется алгоритм сортировки Arrays.sort() (в JVM), который модифицирует исходный список.

Пример базового использования

data class Person(val name: String, val age: Int)

fun main() {
    val people = mutableListOf(
        Person("Alice", 30),
        Person("Bob", 25),
        Person("Charlie", 35)
    )
    
    // Сортировка по возрастанию возраста
    people.sortBy { it.age }
    
    println(people) // [Person(name=Bob, age=25), Person(name=Alice, age=30), Person(name=Charlie, age=35)]
}

Ключевые особенности

  • Только для изменяемых коллекций: sortBy работает с MutableList<T>, MutableCollection<T> и т.д.
  • Естественный порядок: Ключи должны быть Comparable.
  • Сортировка на месте: Исходный список изменяется.

Альтернативы для разных случаев

Для неизменяемых коллекций используйте sortedBy:

val immutableList = listOf(Person("Alice", 30), Person("Bob", 25))
val sortedList = immutableList.sortedBy { it.age } // Возвращает новый список

Для обратной сортировки используйте sortByDescending:

people.sortByDescending { it.age } // Сортировка по убыванию

Для сложной сортировки используйте sortWith:

people.sortWith(compareBy<Person> { it.age }.thenBy { it.name })

Внутренняя реализация

В исходном коде Kotlin sortBy выглядит так:

public inline fun <T, R : Comparable<R>> MutableList<T>.sortBy(crossinline selector: (T) -> R?) {
    if (size > 1) sortWith(compareBy(selector))
}

Как видно, внутри используется:

  1. sortWith — общая функция сортировки с компаратором
  2. compareBy — создает компаратор из селектора
  3. Проверка size > 1 — оптимизация для пустых или одноэлементных списков

Особенности производительности

  • Временная сложность: O(n log n) в среднем случае
  • Пространственная сложность: O(n) в худшем случае (использует дополнительную память)
  • Стабильность: Алгоритм Arrays.sort() в Kotlin/JVM является стабильной сортировкой, что сохраняет порядок равных элементов.

Практические рекомендации

  1. Для примитивных типов можно использовать специализированные функции:
val ints = mutableListOf(5, 2, 8)
ints.sort() // Специализированная функция для Int
  1. Null-безопасность: sortBy корректно обрабатывает nullable ключи:
val list = mutableListOf("banana", null, "apple", null)
list.sortBy { it } // null будут в начале списка
  1. Ленивое вычисление: Селектор вызывается один раз для каждого элемента при сортировке.

Подводные камни

// Неэффективно для больших объектов
people.sortBy { it.calculateExpensiveKey() }

// Лучше использовать:
people.sortWith(Comparator { p1, p2 -> 
    p1.calculateExpensiveKey().compareTo(p2.calculateExpensiveKey())
})

Сравнение с Java

// Kotlin
people.sortBy { it.age }

// Java эквивалент
people.sort(Comparator.comparing(Person::getAge));

sortBy в Kotlin предоставляет более декларативный и лаконичный синтаксис по сравнению с Java.

Заключение

sortBy — это удобная функция высшего порядка, которая сочетает:

  • Лаконичность за счет лямбда-синтаксиса
  • Безопасность типов благодаря системе типов Kotlin
  • Эффективность за счет использования стандартных алгоритмов сортировки

Для большинства случаев сортировки по одному полю sortBy является оптимальным выбором, но для сложных сценариев стоит использовать sortWith с кастомными компараторами.

Как работает sortBy в Kotlin? | PrepBro