class Foo(val a: String, val b: Int, val c: Date)
があり、3つのプロパティすべてに基づいてFoo
sのリストをソートするとします。これについてどうすればいいですか?
Kotlinのstdlibは、このための便利なヘルパーメソッドを多数提供しています。
最初に、 compareBy()
メソッドを使用してコンパレータを定義し、それを sortedWith()
拡張メソッドに渡して、ソートされたコピーを受け取ることができますリストの:
_val list: List<Foo> = ...
val sortedList = list.sortedWith(compareBy({ it.a }, { it.b }, { it.c }))
_
第二に、 compareValuesBy()
ヘルパーメソッドを使用して、Foo
に_Comparable<Foo>
_を実装させることができます。
_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 })
}
_
次に、パラメータなしで sorted()
拡張メソッドを呼び出して、リストのソートされたコピーを受け取ることができます。
_val sortedList = list.sorted()
_
一部の値を昇順でソートし、他の値を降順でソートする必要がある場合、stdlibはそのための関数も提供します。
_list.sortedWith(compareBy<Foo> { it.a }.thenByDescending { it.b }.thenBy { it.c })
_
vararg
のcompareValuesBy
バージョンはバイトコードにインライン化されません。つまり、ラムダに対して匿名クラスが生成されます。ただし、ラムダ自体が状態をキャプチャしない場合、毎回ラムダをインスタンス化する代わりにシングルトンインスタンスが使用されます。
コメントの Paul Woitaschek で述べたように、複数のセレクターと比較すると、vararg呼び出しの配列が毎回インスタンス化されます。呼び出しごとにコピーされるため、配列を抽出して最適化することはできません。一方、できることは、ロジックを静的コンパレータインスタンスに抽出して再利用することです。
_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)
}
}
_