¿Cómo orderar basado en / comparar múltiples valores en Kotlin?

Digamos que tengo una class Foo(val a: String, val b: Int, val c: Date) y quiero orderar una list de Foo basada en las tres properties. ¿Cómo voy a hacer esto?

Kotlin's stdlib ofrece varios methods útiles de ayuda para esto.

Primero, puede definir un comparador usando el método compareBy() y pasarlo al método de extensión sortedWith() para recibir una copy orderada de la list:

 val list: List<Foo> = ... val sortedList = list.sortedWith(compareBy({ it.a }, { it.b }, { it.c })) 

En segundo lugar, puede permitir que Foo implemente Comparable<Foo> utilizando el método de ayuda compareValuesBy() :

 class Foo(val a: String, val b: Int, val c: Date) : Comparable<Foo> { override fun compareTo(other: Foo) = compareValuesBy(this, other, { it.a }, { it.b }, { it.c }) } 

Luego puede llamar al método de extensión sorted() sin parameters para recibir una copy orderada de la list:

 val sortedList = list.sorted() 

Dirección de sorting

Si necesita orderar ascendente en algunos valores y descender en otros valores, stdlib también ofrece funciones para eso:

 list.sortedWith(compareBy<Foo> { it.a }.thenByDescending { it.b }.thenBy { it.c }) 

Consideraciones de performance

La versión vararg de compareValuesBy no está en línea en bytecode, lo que significa que se generarán classs anónimas para las lambdas. Sin embargo, si las lambdas no capturan el estado, se usarán instancias únicas en lugar de instanciar las lambdas cada vez.

Como señaló Paul Woitaschek en los comentarios, la comparación con selectores múltiples instanciará una matriz para la llamada vararg cada vez. No puede optimizar esto extrayendo la matriz, ya que se copyrá en cada llamada. Lo que puede hacer, por otro lado, es extraer la lógica en una instancia comparativa estática y reutilizarla:

 class Foo(val a: String, val b: Int, val c: Date) : Comparable<Foo> { override fun compareTo(other: Foo) = comparator.compare(this, other) companion object { // using the method reference syntax as an alternative to lambdas val comparator = compareBy(Foo::a, Foo::b, Foo::c) } } 
  • KotlinNullPointerException: inside onCreateOptionsMenu no puede encontrar searchView; android
  • Filtro de list dentro del range externo - KOTLIN
  • ¿Se puede utilizar javascript generado a partir de fonts de Kotlin en JVM?
  • ¿Cómo cambiar el color de background de una vista de carta cuando se selecciona?
  • ¿Cómo manejar un param vacío en Kotlin?
  • Las células RecyclerView se deforman cuando se abre el keyboard
  • Kotlin generics no coinciden en una jerarquía de classs
  • Flutter: cómo lanzar y la intención de Android y devolver datos para aletear
  • Comparta el código entre la testing unitaria y las testings de instrumentación cuando use kotlin
  • Imprima todos los types de file de inicio de session usando registrador
  • Convierta Any a ArrayList en Kotlin, Retrofit