Java转Kotlin:操作符重载案例

556 阅读2分钟

案例1:重写Person类的equals与hashCode

背景

用一个HashSet承载Person对象,并认为nameage相同的对象为同一个对象,希望HashSet中的对象不重复。

实现

main函数

添加5个相同的对象到HashSet中,并打印该HashSetsize

//Kotlin
var persons = HashSet<Person>()

fun main() {
    (1..5).forEach { persons.add(Person("Ton", 25)) }
    println(persons.size)
}

未处理的Person类

//Kotlin
class Person(val name: String, val age: Int)

控制台打印结果

每一个Person("Ton", 25)对象都在堆上的不同内存区域,HashSet判断对象是否equals时,因为地址不一样,HashSet认为是不同的对象,所有5个对象都添加进了集合。

重写equals的Person

//Kotlin
class Person(val name: String, val age: Int) {
    override fun equals(other: Any?): Boolean {
        val other = (other as? Person) ?: return false//注意elvis表达式
        return this.name == other.name && this.age == other.age
    }
}

控制台打印结果

结果还是5,原因很简单:HashSet比较两个对象是否equals前,会先比较两个对象的hashCode,因为还没有重写Person类的hashCode()方法,因此,仅仅重写equals()方法在此场景中是无效的。

重写equals和hashCode的Person

//Kotlin
class Person(val name: String, val age: Int) {
    override fun equals(other: Any?): Boolean {
        val other = (other as? Person) ?: return false
        return this.name == other.name && this.age == other.age
    }

    override fun hashCode(): Int {
        return age.hashCode() + name.hashCode()
    }
}

控制台打印结果

  • 为什么这是一个操作符重载的案例呢?
  • 重载操作符不是需要operator关键字吗?

Person类的父类Anyequals()方法,有operator关键字。

案例2:为String实现四则运算

背景

String类实现+-*/四则运算。

  • +:将前后两个字符串连接起来;
  • -:若前面的字符串包含后面字符串,则删除所有与后面字符串相同的子串;
  • *:将前面的字符串重复times遍;
  • /:判断前面的字符串包含多少个后面的字符串。

实现

操作符重载

//Kotlin

// +
operator fun String.plus(other: Any?): String {
    val other = (other.toString() as? String) ?: throw IndexOutOfBoundsException()
    return "${this}${other}"
}

// -
operator fun String.minus(other: Any?): String {
    val other = (other.toString() as? String) ?: throw IndexOutOfBoundsException()
    var res: String = ""
    if (this.length < other.length) return this
    var delete = HashSet<Int>()
    this.indices.forEach {
        if (!delete.contains(it)) {
            if (it + other.length <= this.length) {
                if (this.substring(it, it + other.length) == other) {
                    for (i in (it until it + other.length)) {
                        delete.add(i)
                    }
                }
            }
        }
    }
    this.indices.forEach {
        res += if (delete.contains(it)) "" else this[it]
    }
    return res
}

// *
operator fun String.times(times: Int): String = (1..times).joinToString("") { this }

// /
operator fun String.div(other: Any?): Int {
    val other = (other.toString() as? String) ?: throw IndexOutOfBoundsException()
    var res: Int = 0
    if (this.length<other.length || !this.contains(other)) return res
    this.indices.forEach {
        if (it + other.length <= this.length) {
            if (this.substring(it, it + other.length) == other) {
                res++
            }
        }
    }
    return res
}

main函数

//Kotlin
fun main() {
    val s1 = "abcd"
    val s2 = "efg"
    val s3 = s1 + s2;
    println(s3)
    val s4 = "abcbcabcd"
    val s5 = "abc"
    val s6 = s4 - s5
    println(s6)
    val s7 = "Hello"
    val s8 = s7.times(7)
    println(s8)
    val s9 = "abcabcabc"
    val s10 = "abc"
    val i = s9 / s10
    println(i)
}

控制台打印结果