1. 概述
String
是 Kotlin 中最常用的数据类型之一,字符串操作在日常开发中极为频繁。本文将系统介绍几种在 Kotlin 中移除字符串第一个字符的常用方式,并对比它们在边界情况(如空字符串)下的表现。
由于字符串在 Kotlin(以及 Java)中是不可变的(immutable),所谓“移除”实际上是生成一个新字符串对象。这一点无需赘述,相信有经验的读者早已了然于心 ✅。
2. 问题分析
核心目标很明确:给定一个字符串,返回去掉首字符后的新字符串。关键在于处理以下边界情况:
- 字符串为空(
""
) - 字符串只有一个字符
我们将通过单元测试验证每种方法的行为,确保其健壮性。下面进入正题。
3. 使用 drop()
函数 ✅ 推荐
Kotlin 提供了丰富的字符串扩展函数,其中 drop(n)
可以直接丢弃前 n
个字符,非常适合本场景。
val myStr = "0a b c d e"
val result = myStr.drop(1)
assertEquals("a b c d e", result)
✅ 优点:
- 语法简洁,语义清晰
- 对空字符串安全:
"".drop(1)
返回空字符串""
,不会抛异常
val result2 = "".drop(1)
assertEquals("", result2) // 正常通过
⚠️ 踩坑提醒:这是最推荐的方式,兼顾简洁与安全性,建议作为首选方案。
4. 使用 substring()
方法 ⚠️ 注意空串
substring(beginIndex)
可以获取从指定索引开始到末尾的子串。要去掉首字符,只需从索引 1
开始截取:
val myStr = "0a b c d e"
val result = myStr.substring(1)
assertEquals("a b c d e", result)
❌ 致命缺陷:当输入为空字符串时,substring(1)
会抛出 IndexOutOfBoundsException
:
assertThrows<IndexOutOfBoundsException> {
"".substring(1)
}
⚠️ 适用场景:仅当你能100%确保输入非空时才可使用,否则需额外判空,增加代码复杂度。
5. 使用 takeLast()
函数 ❌ 不推荐
takeLast(n)
返回字符串末尾的 n
个字符。因此,可以通过 takeLast(length - 1)
来排除首字符:
val myStr = "0a b c d e"
val result = myStr.takeLast(myStr.length - 1)
assertEquals("a b c d e", result)
你也可以使用 lastIndex
属性替代 length - 1
,语义更清晰:
// CharSequence 的扩展属性
public val CharSequence.lastIndex: Int
get() = this.length - 1
val result = myStr.takeLast(myStr.lastIndex)
❌ 严重问题:当字符串为空时,length - 1
为 -1
,触发 IllegalArgumentException
:
val myEmpty = ""
assertThrows<IllegalArgumentException> {
myEmpty.takeLast(myEmpty.length - 1)
}.also {
assertEquals("Requested character count -1 is less than zero.", it.message)
}
⚠️ 结论:此方法不够健壮,不推荐用于通用场景。
6. 使用正则 replace()
方法 ✅ 可选方案
利用正则表达式匹配并替换首字符也是一种思路:
val myStr = "0a b c d e"
val result = myStr.replace("^.".toRegex(), "")
assertEquals("a b c d e", result)
- 正则
^.
表示匹配行首的任意一个字符 - 替换为空字符串,即实现“删除”
✅ 优势:
- 对空字符串友好:
"".replace("^.".toRegex(), "")
返回""
- 不依赖索引,逻辑独立
⚠️ 缺点:
- 性能略低于纯字符串操作(涉及正则引擎)
- 代码可读性不如
drop(1)
✅ 适用场景:适合对性能不敏感且希望统一使用正则处理的项目。
7. 总结
方法 | 空字符串安全 | 推荐程度 | 说明 |
---|---|---|---|
drop(1) |
✅ 是 | ⭐⭐⭐⭐⭐ | 最佳选择,简洁安全 |
substring(1) |
❌ 否 | ⭐⭐ | 需额外判空,易踩坑 |
takeLast(length-1) |
❌ 否 | ⭐ | 边界处理差,不推荐 |
replace("^.".toRegex(), "") |
✅ 是 | ⭐⭐⭐⭐ | 可用,但略重 |
✅ 最终建议:优先使用 drop(1)
,它在可读性、安全性和性能之间达到了最佳平衡。
完整示例代码已托管至 GitHub:https://github.com/Baeldung/kotlin-tutorials/tree/master/core-kotlin-modules/core-kotlin-strings-4