当前位置:网站首页>有趣的 Kotlin 0x06:List minus list

有趣的 Kotlin 0x06:List minus list

2022-07-28 15:42:00 AndroidKt

最近在 http://portal.kotlin-academy.com/#/ 上看到很多关于 Kotlin 的有趣的题目。个人觉得很适合 Kotlin 爱好者,感兴趣的小伙伴可自行查阅。
【有趣的 Kotlin 】系列记录自己对每一题的理解。

0x06:List minus list

fun main(args: Array<String>) {
    
    val list = listOf(1, 2, 3)
    print(list - 1)
    print(list - listOf(1))

    val ones = listOf(1, 1, 1)
    print(ones - 1)
    print(ones - listOf(1))
}

以上代码,运行结果是什么?可选项:

  1. [2, 3][2, 3][1, 1][1, 1]
  2. [2, 3][2, 3][1, 1][]
  3. [2, 3][2, 3][][1, 1]
  4. [2, 3][2, 3][][]

思考一下,记录下你心中的答案。

分析

题目如上,熟悉 Kotlin 集合相关操作符逻辑的朋友应该能很快能得到答案,这里只涉及 - 一个运算符和两个重载实现。

第一个重载实现:

第一个重载

逻辑就是过滤掉集合中第一个与传入参数 element 相等的元素。

第二个重载实现:

另一个重载

逻辑就是过滤掉与第二个列表中的任意元素相等的所有元素。

题中代码等价于如下写法:

fun main(args: Array<String>) {
    
    val list = listOf(1, 2, 3)
    print(list.minus(1))
    print(list.minus(listOf(1)))

    val ones = listOf(1, 1, 1)
    print(ones.minus(1))
    print(ones.minus(listOf(1)))
}

逐个查看运算逻辑

val list = listOf(1, 2, 3)
print(list - 1)           // 过滤掉第一个等于 1 的元素,结果为 [2, 3]
print(list - listOf(1))   // 过滤掉所有等于 1 的元素,结果为 [2, 3]

val ones = listOf(1, 1, 1)
print(ones - 1)           // 过滤掉第一个等于 1 的元素,结果为 [2, 3]
print(ones - listOf(1))   // 过滤掉所有等于 1 的元素,结果为 []

所以,正确答案为

选项 2 :[2, 3][2, 3][1, 1][]

延伸

Kotlin 中使用 operator 关键字用于修饰函数,表示该函数重载一个操作符或者实现一个约定。使用 operator 关键字修饰函数并且函数名只能为component1component2component3 … 时则是实现一个约定,即 解构

顺便看看 List 的一些其他操作符(in+)以及 解构约定。

fun main() {
    
    val list = listOf(1, 2, 3)
    println(2 in list)
    println(4 in list)
    println(list + 5)
    println(list + listOf(1, 2, 3))
    println(list + arrayOf(1, 2, 3))
    println(list + sequenceOf(1, 2, 3))

    val (v, w, x) = list
    println(v)
    println(w)
    println(x)
    
    println(list.component1())
    println(list.component2())
    println(list.component3())
    println(list.component4())
    println(list.component5())

}

运行结果如下:

运行结果

componentN 最多支持到 5, 且 receiver 为 List<T>,内部其实调用的就是 get() 函数,所以当索引超出列表长度时,运行时报错。

针对 operatorcomponentN 的配合方式,举例说明一下:

class Location(val x: Int, val y: Int) {
    
    operator fun component1() = x
    operator fun component2() = y
}

fun main() {
    
    val location = Location(520, 1314)
    val (x, y) = location

    println(x)
    println(y)
}

运行结果:

解构

针对操作符重载,也举例说明下:

operator fun Location.minus(location: Location): Location {
    
    return Location(this.x - location.x, this.y - location.y)
}

operator fun Location.plus(location: Location): Location {
    
    return Location(this.x + location.x, this.y + location.y)
}

operator fun Location.contains(location: Location): Boolean {
    
    return this.x > location.x && this.y > location.y
}


class Location(val x: Int, val y: Int) {
    
    operator fun component1() = x
    operator fun component2() = y

    override operator fun equals(other: Any?): Boolean =
        other is Location && this.x == other.x && this.y == other.y

    override fun hashCode(): Int {
    
        var result = x
        result = 31 * result + y
        return result
    }

    override fun toString(): String {
    
        return "($x, $y)"
    }
}

fun main() {
    
    val location = Location(520, 1314)
    val (x, y) = location

    println(x)
    println(y)

    val other = Location(1, 2)
    println(location - other)
    println(location + other)
    println(location == other)
    println(other in location)
}

运行结果如下:

运行结果

注意一下:equals 操作符重载只能作为类成员函数实现,因为此函数已在 Any 类中定义。

编写过程中, Android Studio 会给予我们友好的提示,不愧是 YYDS 。

Android Studio YYDS

总结

  • 操作符重载
  • 解构
原网站

版权声明
本文为[AndroidKt]所创,转载请带上原文链接,感谢
https://onlyloveyd.blog.csdn.net/article/details/118093513