Supposons que j’ai une class Foo(val a: String, val b: Int, val c: Date)
et que je veuille trier une liste de Foo
s en fonction de ces trois propriétés. Comment pourrais-je m'y prendre?
Stdlib de Kotlin propose un certain nombre de méthodes d’aide utiles à cet égard.
Tout d'abord, vous pouvez définir un comparateur à l'aide de la méthode compareBy()
et le transmettre à la méthode d'extension sortedWith()
pour recevoir une copie triée. de la liste:
val list: List<Foo> = ...
val sortedList = list.sortedWith(compareBy({ it.a }, { it.b }, { it.c }))
Deuxièmement, vous pouvez laisser Foo
implémenter Comparable<Foo>
À l'aide de la méthode d'assistance 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 })
}
Ensuite, vous pouvez appeler la méthode d’extension sorted()
sans paramètres pour recevoir une copie triée de la liste:
val sortedList = list.sorted()
Si vous avez besoin de trier par ordre croissant sur certaines valeurs et par ordre décroissant, stdlib propose également des fonctions pour cela:
list.sortedWith(compareBy<Foo> { it.a }.thenByDescending { it.b }.thenBy { it.c })
La version vararg
de compareValuesBy
n'est pas insérée dans le bytecode, ce qui signifie que des classes anonymes seront générées pour les lambdas. Toutefois, si les lambdas eux-mêmes ne capturent pas l'état, des instances de singleton seront utilisées au lieu d'instancier à chaque fois les lambdas.
Comme indiqué par Paul Woitaschek dans les commentaires, la comparaison avec plusieurs sélecteurs instanciera un tableau pour l'appel vararg à chaque fois. Vous ne pouvez pas optimiser cela en extrayant le tableau car il sera copié à chaque appel. Par contre, vous pouvez extraire la logique dans une instance de comparateur statique et la réutiliser:
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)
}
}