案例1:重写Person类的equals与hashCode
背景
用一个HashSet
承载Person
对象,并认为name
和age
相同的对象为同一个对象,希望HashSet
中的对象不重复。
实现
main函数
添加5个相同的对象到HashSet
中,并打印该HashSet
的size
。
//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
类的父类Any
的equals()
方法,有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)
}
控制台打印结果
