Kotlin中的List排序
一、排序的简单用法
在Java中,对List进行排序可以使用Collections.sort()方法,在Kotlin中有非常简单的语法糖,所以这里记录一下,开发中尽量用简单的方式,方便维护。
一段未排序的示例代码如下:
data class User(val name: String, val isOnline: Boolean)
fun main() {
val user1 = User("1", false)
val user2 = User("2", false)
val user3 = User("3", true)
val user4 = User("4", true)
val userList = mutableListOf(user4, user3, user2, user1)
userList.forEach(::println)
}
输出结果如下:
User(name=4, isOnline=true)
User(name=3, isOnline=true)
User(name=2, isOnline=false)
User(name=1, isOnline=false)
我们希望按用户名进行排序,实现代码如下:
userList.sortBy { user -> user.name } // 指定以name属性进行升序排序
userList.sortByDescending { user -> user.name } // 指定以name属性进行降序排序
升序排序的打印结果如下:
User(name=1, isOnline=false)
User(name=2, isOnline=false)
User(name=3, isOnline=true)
User(name=4, isOnline=true)
Kotlin中的排序就是这么简单,如果我们把列表声明为不可变的列表,则不能使用sortBy或sortByDescending方法,因为列表不可以改变嘛。对于不可变列表的排序可以使用sortedBy或sortedBytDescending方法,方法名差不多,只是多了ed两个字母,它的实现是创建一个新的列表来保存排序后的结果,示例如下:
val userList = listOf(user4, user3, user2, user1)
val newList = userList.sortedBy { user -> user.name }
newList.forEach(::println)
二、排序的高级用法
查看sortBy和sortByDescending的源码发现,其是通过调用sortWith方法实现的,对应的sortedBy和sortedByDescending则是通过调用sortedWith方法实现的,sortWith的功能和sortedWith的功能原理是一样的,所以我这里讲清楚sortWith的使用即可。
-
使用sortWith实现升序排序
val userList = mutableListOf(user4, user3, user2, user1) userList.sortWith(kotlin.Comparator {u1, u2 -> u1.name.compareTo(u2.name) }) userList.forEach(::println)
-
使用sortWith实现降序排序
降序非常简单,把u1和u2的比较顺序交换一下即可
userList.sortWith(kotlin.Comparator {u1, u2 -> u2.name.compareTo(u1.name) })
-
使用sortWith实现多重排序
sortBy只能指定一个属性参与排序,并且此属性对象必须已经实现了Comparable接口,通过调用该接口的compare方法进行排序,而使用sortWith则可以指定多个属性参与排序,属性不需要实现Comparable接口,可以自己定制排序的逻辑。
假设我们希望按用户的在线状态排序,在线的排前面,离线的排后面,状态相同的情况下再按名称排序,实现代码如下:
fun main() { val user1 = User("1", false) val user2 = User("2", false) val user3 = User("3", true) val user4 = User("4", true) val userList = mutableListOf(user2, user1, user4, user3) println("排序前:") userList.forEach(::println) userList.sortWith(kotlin.Comparator { u1, u2 -> if (u1.isOnline != u2.isOnline) { u2.isOnline.compareTo(u1.isOnline) // 状态以降序排序 } else { u1.name.compareTo(u2.name) // 名字以升序排序 } }) println("排序后:") userList.forEach(::println) }
输出结果如下:
排序前: User(name=2, isOnline=false) User(name=1, isOnline=false) User(name=4, isOnline=true) User(name=3, isOnline=true) 排序后: User(name=3, isOnline=true) User(name=4, isOnline=true) User(name=1, isOnline=false) User(name=2, isOnline=false)
再一次感受到了Kotlin的强大,真是太方便了,使用Kotlin进行开发可以节省我们大量的宝贵时间。
2023-10-29续:刚刚发现还有更强大的,可以一次指定用多个属性排序,如下:
userList.sortedWith(
compareBy({ it.isOnline }, { it.name })
)
这种用法要求指定的属性实现了Comparable接口。
因为是sortedWith函数,所以指定的是升序,那么它就会先按在线状态升序,然后再按名字升序,所以打印的结果如下:
排序前:
User(name=2, isOnline=false)
User(name=1, isOnline=false)
User(name=4, isOnline=true)
User(name=3, isOnline=true)
排序后:
User(name=1, isOnline=false)
User(name=2, isOnline=false)
User(name=3, isOnline=true)
User(name=4, isOnline=true)
这种做法的缺点就是都是升序,能不能指定一个升序一个降序呢?此时就要用上与 thenBy 的结合了,实现上面的功能,使用 compareBy 和 thenBy 感觉代码更加清晰,如下:
userList.sortWith(
compareBy(User::isOnline).thenBy(User::name)
)
thenBy 是 Comparator 的扩展函数,它的原理也比较简单,先按 Comparator 的进行比较,如果不相同则按 Comparator 的进行排序,如果相同的话再按 thenBy 中指定的进行排序。compareBy 与 thenBy 都有对应的降序函数:compareByDescending、thenByDescending,所以我们就可以随便组合升序和降序了,比如先按状态降序排序,然后再按名字升序排序,如下:
userList.sortWith(
compareByDescending(User::isOnline).thenBy(User::name)
)
这个多重的降序升序逻辑太简单太清晰了,哇,简直不要太爽了^_^
!
更多推荐
所有评论(0)