侧边栏壁纸
博主头像
Z同学博主等级

工作磨平激情前,坚持技术的热忱。 欢迎光临Z同学的技术小站。 分享最新的互联网知识。

  • 累计撰写 290 篇文章
  • 累计创建 57 个标签
  • 累计收到 98 条评论

Kotlin 集合 排序详解

Z同学
2021-10-11 / 0 评论 / 1 点赞 / 1,321 阅读 / 5,288 字
温馨提示:
本文最后更新于 2021-11-18,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

前言

本篇文章,我们开始学习Kotlin中集合的排序操作

实际使用中,我们针对集合对象的排序属于高频操作了。

那么Kotlin是如何给我们提供集合的排序呢?排序是有别于Group分组的。

关于分组已经有相关的文档进行介绍了。

在添加集合时,我们默认不设置任何排序属性。集合是按照默认顺序进行添加的。

也就是说,我们怎么添加的。在集合中的顺序就是怎么样的。

我们排序,都是针对集合数据已经有值的情况下。重新调整集合里面的元素排放位置。

引读

针对集合已经有4篇文章进行过介绍。如果需求了解集合的其他功能,可以通过下面的链接进行跳转。

Kotlin 集合 基本介绍 - Z同学 (zinyan.com)

Kotlin 集合 转换,过滤和检测 - Z同学 (zinyan.com)

Kotlin 集合 plus,minus和分组group详解 - Z同学 (zinyan.com)

Kotlin 集合 查询,检测,截取等方法介绍 - Z同学 (zinyan.com)

自然排序

kotlin 已经实现了的排序方式,我们只需要调用sorted或者sortedDescending 就能快捷实现。

元素从大到小和从小到大的排序。

sorted() 从小到大排序

kotlin给集合对象实现了一个sorted() 函数,实现了默认的自然排序效果。

也就是按照数值的从小到大进行排序。

如果集合对象是int型等数值,就会按照:0至1的顺序进行排序

如果集合对象是Char或者String :就会按照字符的字典顺序进行排序,也就是a,b,c,d... 等

示例:

fun main(string: Array<String>) {
    //int 型
    val intT = listOf(1, 2, 3, 0, 23, 54, 222, 9, 5)
    println("实际结果:$intT")
    println("排序结果:${intT.sorted()}")
    //字符串
    var test = listOf("A", "c", "b", "Y", "f", "x", "X")
    println("实际结果:$test")
    println("排序结果:${test.sorted()}")
    //float
    val floatT = listOf(0.1, 2.4, 1.0, 2.3, 4.5, 1.3)
    println("实际结果:$floatT")
    println("排序结果:${floatT.sorted()}")
}
//输出
实际结果:[1, 2, 3, 0, 23, 54, 222, 9, 5]
排序结果:[0, 1, 2, 3, 5, 9, 23, 54, 222]
实际结果:[A, c, b, Y, f, x, X]
排序结果:[A, X, Y, b, c, f, x]
实际结果:[0.1, 2.4, 1.0, 2.3, 4.5, 1.3]
排序结果:[0.1, 1.0, 1.3, 2.3, 2.4, 4.5]

这种是按照元素值的自动顺序进行升序排序。那么我们如果需要降序呢?

sortedDescending() 从大到小进行排序

排序要求是一样的,只是顺序进行了调整实现了从大到小的排序。

示例:

fun main(string: Array<String>) {
    //int 型
    val intT = listOf(1, 2, 3, 0, 23, 54, 222, 9, 5)
    println("实际结果:$intT")
    println("排序结果:${intT.sortedDescending()}")
}
//输出
实际结果:[1, 2, 3, 0, 23, 54, 222, 9, 5]
排序结果:[222, 54, 23, 9, 5, 3, 2, 1, 0]

上面的排序方式有几个限制。

不支持自定义元素的排序,不支持多种参数类型混合的集合对象排序。字符串都是取首字母进行判断

那么就需要我们自定义排序条件了。

自定义顺序

我们可以自己决定排序的判断条件。

下面将从简单到复杂来介绍各种自定义排序的方法的使用。

sortedBy()

主要自定义sorted的排序逻辑。按照我们定义的函数进行排序。

示例:

fun main(string: Array<String>) {
    val intT = listOf("aaa", "vvv", "edde", "asdjiof", "fdioja")
    println("实际结果:$intT")
    println("自然排序:${intT.sorted()}")
    println("自定义排序:${intT.sortedBy { it.length }}")
}
//输出
实际结果:[aaa, vvv, edde, asdjiof, fdioja]
自然排序:[aaa, asdjiof, edde, fdioja, vvv]
自定义排序:[aaa, vvv, edde, fdioja, asdjiof]

例如上面的例子。我们自然排序时将会按照字符串的首字母进行排序。

我们自定义排序,让字符串按照他的字符长度进行排序。

我们在sortedBy 方法中定义的代码。必须是可以进行比较的满足sorted的要求的参数才行。

所以,我们可以定义返回char,int,float 等等基本类型值。

针对自定义对象的排序

示例:

class Zx(val x: Int) {
    override fun toString(): String {
        return x.toString()
    }
}

fun main(string: Array<String>) {
    val xx = listOf(Zx(1), Zx(32), Zx(23))
    println("实际结果:$xx")
    println("自定义排序:${xx.sortedBy { it.x }}")
}
//结果
实际结果:[1, 32, 23]
自定义排序:[1, 23, 32]

那么如果集合对象中是多总元素混杂,该如何排序?

示例:

fun main(string: Array<String>) {
    val xx = listOf(1, 0, 0, 5f, 5, 0.3f, 100L, 92)
    println("实际结果:$xx")
    //例如转成short 进行判断
    println("自定义排序:${xx.sortedBy { it.toShort() }}")
}
//输出
实际结果:[1, 0, 0, 5.0, 5, 0.3, 100, 92]
自定义排序:[0, 0, 0.3, 1, 5.0, 5, 92, 100]

如果我们有多个集合,而同时集合的排序方式都是自定义的。

我们可以将排序逻辑写成Comparable 对象。然后分别传给不同的集合对象。

sortedWith()

示例:

fun main(string: Array<String>) {
    val xx1 = listOf(1, 0, 23, 54, 5, 12, 54)
    val xx2 = listOf(3, 34, 43, 14, 98, 75, 92)
    val xx3 = listOf(1, 0, 2, 7, 4, 2, 3)
    val sorteds = Comparator { i1: Int, i2: Int -> i1 - i2 }
    println(xx1.sortedWith(sorteds))
    println(xx2.sortedWith(sorteds))
    println(xx3.sortedWith(sorteds))
}
//输出
[0, 1, 5, 12, 23, 54, 54]
[3, 14, 34, 43, 75, 92, 98]
[0, 1, 2, 2, 3, 4, 7]

我们可以自定义自己的Comparator实现两个元素的判断。

但是:Comparator它接受一个类的两个实例并返回它们之间比较的整数结果。

还有其他的写法,例如

示例:

fun main(string: Array<String>) {
    val text = listOf("one", "two", "three", "four")
    //我们也可以使用 with自定义compareBy,默认两个元素是相同类型的才行
    println(text.sortedWith(compareBy { it.length }))
}
//输出
[one, two, four, three]

其他情况

倒序 reversed()

区别于从大到小排序和从小到大排序。

reversed不改变集合元素的位置。只是改变了顺序。

示例:

fun main(string: Array<String>) {
    val text = listOf("one", "two", "three", "four")
    println(text.reversed())
}
//输出
[four, three, two, one]

也就是说,我们添加数据到集合中的顺序进行了倒置而已。

它还有一个函数asReversed()。

我们使用asReversed 和reversed 都能得到集合的倒叙结果。

但是两者的区别在于

reversed 得到的是一个新的集合对象。源集合对象进行改变。它的结果不会改变。

而asReversed 还是源集合对象,只是得到的一个集合的反向输出结果而已。

两者的使用,根据实际需求进行选择调用。

asReversed要节省内存。毕竟不用拷贝一个新的集合对象。

随机 shuffled()

函数返回一个包含了以随机顺序排序的集合元素的新的 List

示例:

fun main(string: Array<String>) {
    val text = listOf("one", "two", "three", "four")
    println(text.shuffled())
}
//输出
[three, two, one, four]

输出结果是完全随机的。

mutable* 可变集合下排序方法

以上的排序方法,在mutableList等可变集合下。也都是存在的。只是函数名称有一点区别。

例如:

sort(),sortDescending(),sortBy(),sortWith(),shuffle(),reverse() 等等。

示例:

fun main(string: Array<String>) {
    val numbers = mutableListOf("aa", "bbb", "cccc", "ddddd", "eeeeee")

    numbers.sort()
    println("从小到大排序: $numbers")
    numbers.sortDescending()
    println("从大到小排序: $numbers")

    numbers.sortBy { it.length }
    println("按照字符串长度排序: $numbers")
    numbers.sortByDescending { it.last() }
    println("按照字符串首字母,从大到小排序: $numbers")

    numbers.sortWith(compareBy<String> { it.length }.thenBy { it })
    println("自定义,按照字符串长度排序: $numbers")

    numbers.shuffle()
    println("随机排序: $numbers")

    numbers.reverse()
    println("倒序: $numbers")
   
}
//输出
从小到大排序: [aa, bbb, cccc, ddddd, eeeeee]
从大到小排序: [eeeeee, ddddd, cccc, bbb, aa]
按照字符串长度排序: [aa, bbb, cccc, ddddd, eeeeee]
按照字符串首字母,从大到小排序: [eeeeee, ddddd, cccc, bbb, aa]
自定义,按照字符串长度排序: [aa, bbb, cccc, ddddd, eeeeee]
随机排序: [ddddd, cccc, bbb, aa, eeeeee]
倒序: [eeeeee, aa, bbb, cccc, ddddd]

功能是一样的。

到这里与排序相关的介绍就结束了。

1

评论区