Boolean
クラスは、Comparable
インターフェイスを実装しているため、
大小比較をすることができます。
true
と false
のどちらが大きいかは、API ドキュメントや言語仕様書にも記載されていないようですが、
false < true
です(Java の Boolean
クラスと同じです。Java の API ドキュメントには記載されています)。
そのため Boolean
値のコレクションをソートすると
false
が前(インデックスが小さい方)
true
が後ろ(インデックスが大きい方)
に来ます。
listOf(true, false, true, false)
.sorted()
.also { println(it) } // > [false, false, true, true]
ただしこれは直観的とは言いがたいので、
少なくともコメントを付けておいた方がよいでしょう。
listOf(true, false, true, false)
.sorted() // false が前(インデックスが小さい方)に来る
.also { println(it) } // > [false, false, true, true]
コメントなしでも直感的に分かるようにする
次のような、Comparator<Boolean>
オブジェクトを返す関数1を用意しておいて
/** `false < true` であるとする [Comparator] を返す。 */
fun falsesFirst(): Comparator<Boolean> = compareBy { it }
/** `true < false` であるとする [Comparator] を返す。 */
fun falsesLast(): Comparator<Boolean> = compareByDescending { it }
/** `true < false` であるとする [Comparator] を返す。 */
fun truesFirst(): Comparator<Boolean> = compareByDescending { it }
/** `false < true` であるとする [Comparator] を返す。 */
fun truesLast(): Comparator<Boolean> = compareBy { it }
次のように使えば、
コメントを付けなくても直観的に分かるようにできます。
listOf(true, false, true, false)
.sortedWith(falsesFirst())
.also { println(it) } // > [false, false, true, true]
listOf(true, false, true, false)
.sortedWith(falsesLast())
.also { println(it) } // > [true, true, false, false]
listOf(true, false, true, false)
.sortedWith(truesFirst())
.also { println(it) } // > [true, true, false, false]
listOf(true, false, true, false)
.sortedWith(truesLast())
.also { println(it) } // > [false, false, true, true]
現実的な使い方
実際には、Boolean
そのもののコレクションをソートすることはまずなく、
各要素のプロパティなどから計算した Boolean
型の値に応じてソートすることになるでしょう。
その場合は例えば次のようになります。
data class MyClass(
val value: Boolean
)
listOf(MyClass(true), MyClass(false), MyClass(true), MyClass(false))
.sortedWith(
compareBy(falsesFirst()) { it.value }
)
.also { println(it) } // > [MyClass(value=false), MyClass(value=false), MyClass(value=true), MyClass(value=true)]
listOf(MyClass(true), MyClass(false), MyClass(true), MyClass(false))
.sortedWith(
compareBy(falsesLast()) { it.value }
)
.also { println(it) } // > [MyClass(value=true), MyClass(value=true), MyClass(value=false), MyClass(value=false)]
listOf(MyClass(true), MyClass(false), MyClass(true), MyClass(false))
.sortedWith(
compareBy(truesFirst()) { it.value }
)
.also { println(it) } // > [MyClass(value=true), MyClass(value=true), MyClass(value=false), MyClass(value=false)]
listOf(MyClass(true), MyClass(false), MyClass(true), MyClass(false))
.sortedWith(
compareBy(truesLast()) { it.value }
)
.also { println(it) } // > [MyClass(value=false), MyClass(value=false), MyClass(value=true), MyClass(value=true)]
/以上
-
関数名は
nullsFirst
,nullsLast
に倣いました。 ↩