我需要按名稱的第一個字符對 API 結果進行分組和排序。所有以字母開頭的名稱應按順序排列,然后是以非字母開頭的名稱,分組為“#”并放在末尾。下面是一個簡化的代碼:
data class Model(val title: String)
fun main() {
val mList = arrayListOf(Model("pqr"), Model("abc"), Model("3AM"), Model("%s5"))
val mComparator = Comparator<String> { o1, o2 ->
when {
o1 == "#" -> 1
o2 == "#" -> -1
else -> o1.compareTo(o2)
}
}
val mMap = mList.groupBy {
if (it.title[0].isLetter()) it.title[0].toString()
else "#"
}.toSortedMap(mComparator)
val outList = arrayListOf<List<Model>?>()
mMap.keys.forEach {
outList.add(mMap[it])
}
println(mMap)
println(mMap.keys)
println(mMap.values)
println(mMap["#"])
println(outList)
}
這是上面代碼的輸出:
{a=[Model(title=abc)], p=[Model(title=pqr)], #=[Model(title=3AM), Model(title=%s5)]}
[a, p, #]
[[Model(title=abc)], [Model(title=pqr)], [Model(title=3AM), Model(title=%s5)]]
null
[[Model(title=abc)], [Model(title=pqr)], null]
問題是mMap["#"]給出null盡管mMap、mMap.keys、mMap.values在鍵和相應的值中 顯示“#” 。
不明白為什么mMap["#"]回傳null而不是[Model(title=3AM), Model(title=%s5)]
uj5u.com熱心網友回復:
您的比較器違反了比較器必須滿足的合同。它必須是自反的,這意味著如果交換兩個輸入的順序,它會給出完全相反的結果。比較器的更正版本:
val mComparator = Comparator<String> { o1, o2 ->
when {
o1 == "#" && o2 != "#" -> 1
o2 == "#" && o1 != "#" -> -1
else -> o1.compareTo(o2)
}
}
TreeMap 的功能依賴于正確的 Comparator。顯然,它的比較器在使用時甚至會涉及到treeMap.get,因此在您的情況下,它會回傳 null 的無意義結果。
順便說一句,在變數名前加上“m”前綴是匈牙利表示法,這意味著前綴是成員變數。但這些不是成員變數。它們是區域變數。Kotlin 甚至沒有成員變數,但屬性是類似的。因此,您不應該在這里使用“m”前綴,因為它會錯誤地傳達代碼的含義。無論如何,大多數開發人員避免使用匈牙利符號,因為它使代碼更難閱讀。由于 Android 開發團隊的內部代碼風格,很多官方的 Android 示例都使用它,但這不建議您在自己的代碼中使用它。
uj5u.com熱心網友回復:
val mComparator = Comparator<String> { o1, o2 ->
when {
(o1 == "#").xor(o2 == "#") -> if (o1 == "#") 1 else -1
else -> o1.compareTo(o2)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/411495.html
標籤:
