文章中没有奇淫技巧,都是一些在实际开发中常用,但很容易被我们忽略的一些常见问题,源于平时的总结,这篇文章主要对这些常见问题进行分析。
之前分享过一篇文章 为数不多的人知道的 Kotlin 技巧以及 原理解析 主要分析了一些让人傻傻分不清楚的操作符的原理。
这篇文章主要分析一些常见问题的解决方案,如果使用不当会对 性能 和 内存 造成的那些影响以及如何规避这些问题,文章中涉及的案例来自 Kotlin 官方、Stackoverflow、Medium 等等网站,都是平时看到,然后进行汇总和分析。
通过这篇文章你将学习到以下内容:
- 使用
toLowerCase
和toUpperCase
等等方法会造成那些影响? - 如何优雅的处理空字符串?
- 为什么解构声明和数据类不能在一起使用?
- Kotlin 提供的高效的文件处理方法,以及原理解析?
Sequence
和Iterator
有那些不同之处?- 便捷的
joinToString
方法的使用? - 如何用一行代码实现移除字符串的前缀和后缀?
尽量少使用 toLowerCase 和 toUpperCase 方法
当我们比较两个字符串,需要忽略大小写的时候,通常的写法是调用 toLowerCase()
方法或者 toUpperCase()
方法转换成大写或者小写,然后在进行比较,但是这样的话有一个不好的地方,每次调用 toLowerCase()
方法或者 toUpperCase()
方法会创建一个新的字符串,然后在进行比较。
调用 toLowerCase() 方法
fun main(args: Array<String>) {
// use toLowerCase()
val oldName = "Hi dHL"
val newName = "hi Dhl"
val result = oldName.toLowerCase() == newName.toLowerCase()
// or use toUpperCase()
// val result = oldName.toUpperCase() == newName.toUpperCase()
}
toLowerCase() 编译之后的 Java 代码
如上图所示首先会生成一个新的字符串,然后在进行字符串比较,那么 toUpperCase()
方法也是一样的如下图所示。
toUpperCase() 编译之后的 Java 代码
这里有一个更好的解决方案,使用 equals
方法来比较两个字符串,添加可选参数 ignoreCase
来忽略大小写,这样就不需要分配任何新的字符串来进行比较了。
fun main(args: Array<String>) {
val oldName = "hi DHL"
val newName = "hi dhl"
val result = oldName.equals(newName, ignoreCase = true)
}
equals 编译之后的 Java 代码
使用 equals
方法并没有创建额外的对象,如果遇到需要比较字符串的时候,可以使用这种方法,减少额外的对象创建。
如何优雅的处理空字符串
当字符串为空字符串的时候,返回一个默认值,常见的写法如下所示:
val target = ""
val name = if (target.isEmpty()) "dhl" else target
其实有一个更简洁的方法,可读性更强,使用 ifEmpty
方法,当字符串为空字符串时,返回一个默认值,如下所示。
val name = target.ifEmpty { "dhl" }
其原理跟我们使用 if 表达式是一样的,来分析一下源码。
public inline fun <C, R> C.ifEmpty(defaultValue: () -> R): R where C : CharSequence, C : R =
if (isEmpty()) defaultValue() else this
ifEmpty
方法是一个扩展方法,接受一个 lambda 表达式 defaultValue ,如果是空字符串,返回 defaultValue,否则不为空,返回调用者本身。
除了 ifEmpty
方法,Kotlin 库中还封装很多其他非常有用的字符串,例如:将字符串转为数字。常见的写法如下所示:
val input = "123"
val number = input.toInt()
其实这种写法存在一定问题,假设输入字符串并不是纯数字,例如 123ddd
等等,调用 input.toInt()
就会报错,那么有没有更好的写法呢?如下所示。
val input = "123"
// val input = "123ddd"
// val input = ""
val number = input.toIntOrNull() ?: 0
避免将解构声明和数据类一起使用
这是 Kotlin 团队一个建议:避免将解构声明和数据类一起使用,如果以后往数