避免频繁创建对象
在 Kotlin 中,lambda 表达式用起来特别顺手,比如 list.filter { it > 5 }。但很多人没注意到,每次调用这类高阶函数时,背后的 lambda 都会生成一个匿名类实例。如果这段代码在循环里反复执行,对象创建的开销就会积少成多。
解决办法是尽量复用函数引用,或者使用 inline 关键字标记高阶函数。inline 能让编译器把函数体直接嵌入调用处,省去对象分配。不过别滥用,太大的函数内联反而影响代码体积。
inline fun calculate(list: List<Int>, operation: (Int) -> Int): List<Int> {
return list.map(operation)
}字符串拼接别只用 +
写日志或生成文本时,很多人习惯用 + 拼接字符串,比如 "User: " + name + ", Age: " + age。这种写法在少量拼接时没问题,但如果在循环里拼上百条数据,性能就明显下滑。
这时候应该换成 StringBuilder。它内部维护可变字符数组,避免每次拼接都生成新字符串对象。Kotlin 还提供了 buildString 函数,写起来更简洁。
val result = buildString {
for (i in 1..100) {
append("Item $i\n")
}
}合理使用 data class
data class 自动生成 toString、equals 和 hashCode,开发效率拉满。但如果你只是临时传个参数,根本用不到这些方法,那其实没必要声明成 data class。普通 class 或 sealed class 更轻量。
另外,data class 的 copy() 方法虽然方便,但每次调用都会创建新实例。如果只是读取字段,别为了链式调用连续 copy,容易造成内存压力。
集合操作注意惰性求值
Kotlin 的集合有两类 API:中间操作(如 map、filter)和末端操作(如 first、toList)。中间操作默认是惰性的,只有遇到末端操作才会真正执行。
比如连续写多个 map,不会立刻处理数据。但如果写成 list.map.toMutableList().map,第一个 toMutableList 就触发了计算,后面的 map 又重新遍历,白白浪费资源。保持链式调用到最后再收尾,能减少遍历次数。
用 object 替代单例类
需要全局唯一实例时,Java 里常写双重检查锁或静态内部类。Kotlin 直接提供 object 关键字,一行搞定单例,而且线程安全,初始化还是懒加载的。
object ConfigManager {
var timeout: Int = 30
val headers by lazy { loadDefaultHeaders() }
}比手写单例简洁,也更容易被编译器优化。
属性委托要懂时机
by lazy 是个好东西,适合做延迟初始化。比如某个配置文件解析耗时,但不是启动就必须加载,用 lazy 可以把开销摊到真正使用那一刻。
但要注意线程模式选择。默认 LazyThreadSafetyMode.SYNCHRONIZED 会加锁,多线程安全但有同步开销。如果确定单线程环境,改成 LazyThreadSafetyMode.NONE,速度能快一点。