Ordenação de coleções por vários campos em Kotlin: 5 erros fatais

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que a ordenação "simples" em Kotlin quebra o código?

\n

Olá, colega! Se você já escreveu em Kotlin e tentou ordenar uma lista de tarefas primeiro por data e depois por prioridade, certamente já se deparou com uma situação em que o resultado parece um conjunto aleatório. Você não está sozinho — a pergunta "Sort collection by multiple fields in Kotlin" acumulou milhares de visualizações no Stack Overflow. Parece simples, não? Mas o diabo, como sempre, está nos detalhes.

\n

Neste artigo, vamos analisar os principais erros ao ordenar por vários campos em Kotlin, que até desenvolvedores experientes cometem. Você aprenderá como funciona o sortedWith, por que compareBy e thenBy são seus melhores amigos e como não perder dados devido a null. Vamos lá!

\n\n

Erro nº 1: Ordenar como em Java — usando Comparator manualmente

\n

Kotlin não é Java. Mas muitos, vindos do mundo Java, escrevem:

\n
val list = listOf(\n    User("Alice", 25),\n    User("Bob", 20),\n    User("Charlie", 25)\n)\n\nval sorted = list.sortedWith(Comparator { a, b ->\n    val ageCompare = a.age.compareTo(b.age)\n    if (ageCompare != 0) ageCompare else a.name.compareTo(b.name)\n})\n
\n

Sim, funciona. Mas é terrivelmente ilegível, e você pode facilmente se perder em cadeias de if-else. Kotlin oferece uma maneira elegante — as funções comparadoras.

\n

Como fazer corretamente?

\n
val sorted = list.sortedWith(compareBy<User> { it.age }.thenBy { it.name })\n
\n

Curto, claro, sem lógica desnecessária. compareBy cria o comparador primário, e thenBy adiciona campos secundários. Isso é a ordenação por vários campos em Kotlin em sua forma ideal.

\n\n

Erro nº 2: Ignorar null ao ordenar

\n

Suponha que temos uma lista de tarefas onde deadline pode ser null. Se você simplesmente escrever:

\n
tasks.sortedBy { it.deadline }\n
\n

…você obterá um NullPointerException. Kotlin é rigoroso com null, e isso é ótimo. Mas como proceder se null é algo normal?

\n

Solução: nullsFirst / nullsLast

\n

Use wrappers especiais:

\n
val sorted = tasks.sortedWith(\n    compareBy<Task>(nullsLast()) { it.deadline }\n        .thenBy { it.priority }\n)\n
\n

Aqui, nullsLast() coloca todas as datas nulas no final da lista. Existe também nullsFirst() — o contrário. Isso resolve o problema, e sua ordenação de coleções Kotlin se torna segura.

\n\n

Erro nº 3: Confundir sortedBy com sortedWith

\n

Muitos iniciantes escrevem:

\n
list.sortedBy { it.age }.sortedBy { it.name }\n
\n

E se surpreendem que a ordenação por nome "sobrescreve" a ordenação por idade. sortedBy cria uma nova lista a cada vez e ordena apenas por um campo. A última chamada é a que prevalece.

\n

Como corrigir?

\n

Use sortedWith com a cadeia compareBy:

\n
list.sortedWith(compareBy({ it.age }, { it.name }))\n
\n

Ou a versão multilinha para lógica complexa:

\n
list.sortedWith(compareBy<Person> { it.age }.thenByDescending { it.name })\n
\n

Lembre-se: uma chamada de sortedWith — uma ordenação por vários campos.

\n\n

Erro nº 4: Ordenação em ordem inversa — no lugar errado

\n

Às vezes é necessário ordenar por idade em ordem crescente, mas por nome em ordem decrescente. O erro típico:

\n
list.sortedByDescending { it.age }.sortedBy { it.name }\n
\n

Novamente o mesmo problema — a segunda ordenação quebra a primeira. A abordagem correta:

\n
val sorted = list.sortedWith(\n    compareBy<Person> { it.age }\n        .thenByDescending { it.name }\n)\n
\n

Ou para controle total:

\n
val sorted = list.sortedWith(\n    compareBy(Person::age).thenByDescending(Person::name)\n)\n<                

Blogs

Book Recommendations