## 字符串常见操作
[TOC]
【Kotlin相比于Java,在字符串的处理上做了一些增强】,我们单独来说说字符串这种数据类型。
### **字符串转换**
Kotlin 标准库提供了一套相似的扩展方法,用来把字符串转换成基本数据类型( toInt 、toByte、toBoolean等):
```
println ("42". toInt() )
```
如图所示
![](https://box.kancloud.cn/347ca2de6e8e5ce0544c60f6b94ed767_504x625.png)
每个这样的函数都会尝试把字符串的内容解析成对应的类型,如果解析失败则抛出NumberFormatException 。
### **字符串查找**
在Kotlin中,为了方便字符串的查找,提供了多个函数,如first()、last()、get(index),分别用于查找字符串中的第1个元素、最后1个元素以及角标为index的元素。
```
fun main(args: Array<String>) {
var str = "Hello World!"
println(str.first()) //获取第1个元素
println(str.last()) //获取最后1个元素
println(str.get(4)) //获取第4个元素
println(str[4]) //获取第4个元素
println(str.indexOf('o')) //查找字符串在原字符串中第1次出现的角标
println(str.lastIndexOf( 'o'))//查找字符串在原字符串中最后1次出现的角标
}
```
运行结果
```
H
!
o
o
4
7
```
### **遍历**
**Kotlin里面的字符串支持遍历**,遍历转换成一个个的Char类型。参考代码:
~~~
fun main(args: Array<String>) {
var str: String = "黑马程序员";
for (c in str) {
println(c)
}
}
~~~
输出结果
```
黑
马
程
序
员
Process finished with exit code 0
```
### **字符串替换**
在Kotlin中,除了可以使用Java中的replace()函数实现字符串的替换之外,还可以使用replaceFirst()、replaceAfter()、replaceBefore()等函数用于字符串的替换。
![](https://img.kancloud.cn/13/ee/13ee17b4b54b9ffced67b25cd01b966f_1374x502.png)
```
fun main(args: Array<String>) {
var str = "Hello World! Hello World!"
println(str.replace("World", "Kotlin"))
println(str.replaceFirst("World", "Kotlin"))
println(str.replaceBefore("!", "Kotlin"))
println(str.replaceAfter("Hello ", "Kotlin!"))
}
```
运行结果
```
Hello Kotlin! Hello Kotlin!
Hello Kotlin! Hello World!
Kotlin! Hello World!
Hello Kotlin!
```
### **分割和正则支持:split、toRegex**
再说说字符串分割,同Java,**Kotlin字符串分割也是使用split函数,但是split使用上有些需要注意的**。
split函数源码出自包——[kotlin.text.split](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-text-split.html?lang=en)
![](https://i.loli.net/2019/04/18/5cb89ca55ad46.jpg)
我们先回顾下Java里面的字符串分割函数的使用,参考代码
~~~
class TestDemo {
public static void main(String[] args) {
//字符串
String string = "hello.kotlin.heima";
String[] split = string.split(".");
for (String s : split) {
System.out.println("s:" + s);
}
}
}
~~~
运行结果
```
Process finished with exit code 0
```
针对以上代码,执行结果是什么呢?是的,看不到任何拆分效果,因为,**Java里面的split函数传入的实参,会被默认当做正则表达式**,类似的代码,我们放到Kotlin中,参考代码:
~~~
fun main(args: Array<String>) {
val string = "hello.kotlin.heima"
val split = string.split(".")
for (s in split) {
System.out.println("s:" + s)
}
}
~~~
运行结果
```
s:hello
s:kotlin
s:heima
Process finished with exit code 0
```
针对以上代码,我们看到,字符串拆分成功了。说明**Kotlin中split函数,默认不会把传入的参数当做正则表达式**。那**如果我就是想把传入的参数当做正则表达式呢?怎么办呢?可以通过toRegex方法**,参考代码:
~~~
fun main(args: Array<String>) {
println("hello.kotlin.heima".split("\\.".toRegex()))
}
~~~
运行结果
```
[hello, kotlin, heima]
```
除此之外,**Kotlin的split方法还允许传入多个拆分符**,参考代码:
~~~
fun main(args: Array<String>) {
val string = "hello.kotlin.heima"
val split = string.split(".")
for (s in split) {
println("s:" + s)
}
println("hello.kotlin.heima".split("\\.".toRegex()))
println("hello.kotlin-itheima".split(".", "-"))//传入2个分隔符
}
~~~
运行结果
```
s:hello
s:kotlin
s:heima
[hello, kotlin, heima]
[hello, kotlin, itheima]
Process finished with exit code 0
```
### **截取:[substring](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-text-substring.html?lang=en)、[substringBeforeLast](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-text-substring-before-last.html?lang=en)、[substringAfterLast](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-text-substring-after-last.html?lang=en)**
什么是**字符串截取**?也就是**一个字符串取其中的一部分**。
在java里面字符串截取使用subString方法,**Kotlin同样提供了subString方法。但是,除了subString方法,Kotlin还提供了其他灵活的截图方法**
![](https://img.kancloud.cn/f4/58/f4588cdda4377971af5f85c125e585af_1029x451.png)
![](https://img.kancloud.cn/89/16/89163d4d3833fe9d6e951cbfaec58f9f_1399x494.png)
方法比较多,我们就挑几个方给大家演示演示,参考代码:
~~~
fun main(args: Array<String>) {
val str = "hello kotlin"
println("subString演示:${str.substring(0, 5)}")
val path = "c:/基础语法/字符串分裂.kt"
//获取文件目录
println("${path.substringBeforeLast("/")}")
//获取文件全名(带后缀)
println("${path.substringAfterLast("/")}")
val fileName = "字符串分裂.kt"
//获取文件名
println("${fileName.substringBeforeLast(".")}")
//获取文件拓展名
println("${fileName.substringAfterLast(".")}")
}
~~~
运行结果
```
subString演示:hello
c:/基础语法
字符串分裂.kt
字符串分裂
kt
```
>[info]PS:
substringBeforeLast:返回分隔符最后一次出现之前的子字符串。如果字符串不包含分隔符, 则返回默认为原始字符串的 Missingham长期以来值。
substringAfterLast:返回在最后一次出现分隔符后的之后的子字符串。如果字符串不包含分隔符, 则返回默认为原始字符串的 Missingham长期以来值。
### **去空格**
去除字符串前后的空格在开发过程中是一个常见的需求。Java中通过trim方法去掉字符串空格,Kotlin中同样提供了trim方法,作用同Java。除此之外,在 package kotlin.text 下面的Strings.kt和代码Indent.kt代码中还有trimStart、trimEnd、trimMargin(去除前导空格)、trimIndent(缩进字符串)等方法。我们先看trim、trimStart、trimEnd三个方法,
* [trim](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-text-trim.html?lang=en):去除字符串前后空格
* [trimStart](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-text-trim-start.html?lang=en):去除字符串前面的空格
* [trimEnd](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-text-trim-end.html?lang=en):去除字符串后面的空格
参考代码:
~~~
fun main(args: Array<String>) {
println("${" 内容 ".trim()}")
println("${" 内容 ".trimStart()}")
println("${" 内容 ".trimEnd()}")
}
~~~
运行结果
```
内容
内容
内容
Process finished with exit code 0
```
另外,在 package kotlin.text 下面的Indent.kt代码中,Kotlin还定义了 String 类的扩展函数:
```
fun String.trimMargin(marginPrefix: String = "|"): String
fun String.trimIndent(): String
```
Indent.kt的属性结构图
![](https://box.kancloud.cn/51fc8a6ccf7254e79935488604c57aa6_602x220.png)
我们再看[trimMargin](https://www.w3cschool.cn/doc_kotlin/kotlin-api-latest-jvm-stdlib-kotlin-text-trim-margin.html?lang=en),trimMargin可以去掉前导空格。什么是前导空格呢?也就是每行前面的空格,参考代码:
~~~
fun main(args: Array<String>) {
var str = """ |内容 |内容
|内容
|内容 """.trimMargin()
println(str.trimMargin("|"))
}
~~~
运行结果
```
内容 |内容
内容
内容
Process finished with exit code 0
```
* trimMargin() 函数默认使用 "|" 来作为边界字符:但你可以选择其他字符并作为参数传入,比如 trimMargin(">") 。
* trimIndent() 函数,则是把字符串行的左边空白对齐切割:
```
fun main(args: Array<String>) {
//缩进字符串
val text="""
ABC
123
456"""
println(text.trimIndent())
}
```
运行结果
```
ABC
123
456
Process finished with exit code 0
```
### 字符串字面值
字符串的字面值是一串字符常量,字符串字面值常量是用双引号括起来""的零个或多个字符,如“hello”。Kotlin中有两种类型的字符串字面值,一种是转义字符串,可以包含转义字符,另一种是原生字符串,可以包含转义字符、换行和任意文本。
#### 转义字符串
转义是采用传统的反斜杠“\”方式将字符进行转义。Kotlin中的转义字符串与Java中的转义字符串类似,字符串在输出时,如果想要输出一些特殊字符,则需要用到转义字符串,比如\t,\b,\n,\r,\',\",\\和\$。在这里以\n(换行符)为例,具体代码如下所示
```
fun main(args: Array<String>) {
//字符串中包含转义字符
val str = "您\n好"
println(str)
}
```
运行结果
```
您
好
```
从运行结果可以看出,转义字符串在输出时,并不是保持字符串中原有内容输出,而是输出转义后的内容。
* [ ] 引申:**反斜杠(\)**
反斜杠(\)是一个特殊的字符,被称为转义字符,它的作用是用来转义后面的一个字符。转义后的字符通常用于表示一个不可见的字符或具有特殊含义的字符,例如换行(\n)。下面列出一些常见的转义字符。
* \r:表示回车符,将光标定位到当前行的开头,不会跳到下一行。
* \n:表示换行符,换到下一行开头。
* \t:表示制表符,将光标移动到下一个制表符的位置,类似在文档中用Tab键的效果。
* \b:表示退格符号,类似键盘上的Backspace键。
* \':表示单引号字符,在Kotlin代码中单引号表示字符的开始和结束,如果直接写单引号字符('),程序会认为前两个是一对,会报错,因此需要使用转义字符(\')。
* \":表示双引号字符,Kotlin中双引号表示字符串的开始和结束,包含在字符串中的双引号需要转义,比如""。
* \\:表示反斜杠字符,由于在Kotlin代码中的反斜杠(\)是转义字符,因此需要表示字面意义上的\,就需要使用双反斜杠(\\)。
#### **三重引号**
字符串输出的时候,想要输出一些特殊字符,需要用到转义字符串,比如\\t,\\b,\\n,\\r。转义字符串,在Kotlin里面也是支持的。
Kotlin还新增了一种做法,字符串可以由三重引号(”””)分割,可以直接包含任意的特殊字符,参考代码:
~~~
fun main(args: Array<String>) {
//单行字符串使用转义字符
var str1 = "ccc\n aaa"//通过转义字符换行
println(str1)
//三引号"""包起来的字符串,支持多行
val str2 = """
多行字符串
多行字符串
"""
println(str2)
}
~~~
运行结果
```
ccc
aaa
多行字符串
多行字符串
Process finished with exit code 0
```
- 前言
- Kotlin简介
- IntelliJ IDEA技巧总结
- idea设置类注释和方法注释模板
- 像Android Studion一样创建工程
- Gradle
- Gradle入门
- Gradle进阶
- 使用Gradle创建一个Kotlin工程
- 环境搭建
- Androidstudio平台搭建
- Eclipse的Kotlin环境配置
- 使用IntelliJ IDEA
- Kotlin学习路线
- Kotlin官方中文版文档教程
- 概述
- kotlin用于服务器端开发
- kotlin用于Android开发
- kotlin用于JavaScript开发
- kotlin用于原生开发
- Kotlin 用于数据科学
- 协程
- 多平台
- 新特性
- 1.1的新特性
- 1.2的新特性
- 1.3的新特性
- 开始
- 基本语法
- 习惯用法
- 编码规范
- 基础
- 基本类型
- 包与导入
- 控制流
- 返回与跳转
- 类与对象
- 类与继承
- 属性与字段
- 接口
- 可见性修饰符
- 扩展
- 数据类
- 密封类
- 泛型
- 嵌套类
- 枚举类
- 对象
- 类型别名
- 内嵌类
- 委托
- 委托属性
- 函数与Lambda表达式
- 函数
- Lambda表达式
- 内联函数
- 集合
- 集合概述
- 构造集合
- 迭代器
- 区间与数列
- 序列
- 操作概述
- 转换
- 过滤
- 加减操作符
- 分组
- 取集合的一部分
- 取单个元素
- 排序
- 聚合操作
- 集合写操作
- List相关操作
- Set相关操作
- Map相关操作
- 多平台程序设计
- 平台相关声明
- 以Gradle创建
- 更多语言结构
- 解构声明
- 类型检测与转换
- This表达式
- 相等性
- 操作符重载
- 空安全
- 异常
- 注解
- 反射
- 作用域函数
- 类型安全的构造器
- Opt-in Requirements
- 核心库
- 标准库
- kotlin.test
- 参考
- 关键字与操作符
- 语法
- 编码风格约定
- Java互操作
- Kotlin中调用Java
- Java中调用Kotlin
- JavaScript
- 动态类型
- kotlin中调用JavaScript
- JavaScript中调用kotlin
- JavaScript模块
- JavaScript反射
- JavaScript DCE
- 原生
- 并发
- 不可变性
- kotlin库
- 平台库
- 与C语言互操作
- 与Object-C及Swift互操作
- CocoaPods集成
- Gradle插件
- 调试
- FAQ
- 协程
- 协程指南
- 基础
- 取消与超时
- 组合挂起函数
- 协程上下文与调度器
- 异步流
- 通道
- 异常处理与监督
- 共享的可变状态与并发
- Select表达式(实验性)
- 工具
- 编写kotlin代码文档
- 使用Kapt
- 使用Gradle
- 使用Maven
- 使用Ant
- Kotlin与OSGI
- 编译器插件
- 编码规范
- 演进
- kotlin语言演进
- 不同组件的稳定性
- kotlin1.3的兼容性指南
- 常见问题
- FAQ
- 与Java比较
- 与Scala比较(官方已删除)
- Google开发者官网简介
- Kotlin and Android
- Get Started with Kotlin on Android
- Kotlin on Android FAQ
- Android KTX
- Resources to Learn Kotlin
- Kotlin样品
- Kotlin零基础到进阶
- 第一阶段兴趣入门
- kotlin简介和学习方法
- 数据类型和类型系统
- 入门
- 分类
- val和var
- 二进制基础
- 基础
- 基本语法
- 包
- 示例
- 编码规范
- 代码注释
- 异常
- 根类型“Any”
- Any? 可空类型
- 可空性的实现原理
- kotlin.Unit类型
- kotlin.Nothing类型
- 基本数据类型
- 数值类型
- 布尔类型
- 字符型
- 位运算符
- 变量和常量
- 语法和运算符
- 关键字
- 硬关键字
- 软关键字
- 修饰符关键字
- 特殊标识符
- 操作符和特殊符号
- 算术运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- this关键字
- super关键字
- 操作符重载
- 一元操作符
- 二元操作符
- 字符串
- 字符串介绍和属性
- 字符串常见方法操作
- 字符串模板
- 数组
- 数组介绍创建及遍历
- 数组常见方法和属性
- 数组变化以及下标越界问题
- 原生数组类型
- 区间
- 正向区间
- 逆向区间
- 步长
- 类型检测与类型转换
- is、!is、as、as-运算符
- 空安全
- 可空类型变量
- 安全调用符
- 非空断言
- Elvis操作符
- 可空性深入
- 可空性和Java
- 函数
- 函数式编程概述
- OOP和FOP
- 函数式编程基本特性
- 组合与范畴
- 在Kotlin中使用函数式编程
- 函数入门
- 函数作用域
- 函数加强
- 命名参数
- 默认参数
- 可变参数
- 表达式函数体
- 顶层、嵌套、中缀函数
- 尾递归函数优化
- 函数重载
- 控制流
- if表达式
- when表达式
- for循环
- while循环
- 循环中的 Break 与 continue
- return返回
- 标签处返回
- 集合
- list集合
- list集合介绍和操作
- list常见方法和属性
- list集合变化和下标越界
- set集合
- set集合介绍和常见操作
- set集合常见方法和属性
- set集合变换和下标越界
- map集合
- map集合介绍和常见操作
- map集合常见方法和属性
- map集合变换
- 集合的函数式API
- map函数
- filter函数
- “ all ”“ any ”“ count ”和“ find ”:对集合应用判断式
- 别样的求和方式:sumBy、sum、fold、reduce
- 根据人的性别进行分组:groupBy
- 扁平化——处理嵌套集合:flatMap、flatten
- 惰性集合操作:序列
- 区间、数组、集合之间转换
- 面向对象
- 面向对象-封装
- 类的创建及属性方法访问
- 类属性和字段
- 构造器
- 嵌套类(内部类)
- 枚举类
- 枚举类遍历&枚举常量常用属性
- 数据类
- 密封类
- 印章类(密封类)
- 面向对象-继承
- 类的继承
- 面向对象-多态
- 抽象类
- 接口
- 接口和抽象类的区别
- 面向对象-深入
- 扩展
- 扩展:为别的类添加方法、属性
- Android中的扩展应用
- 优化Snackbar
- 用扩展函数封装Utils
- 解决烦人的findViewById
- 扩展不是万能的
- 调度方式对扩展函数的影响
- 被滥用的扩展函数
- 委托
- 委托类
- 委托属性
- Kotlin5大内置委托
- Kotlin-Object关键字
- 单例模式
- 匿名类对象
- 伴生对象
- 作用域函数
- let函数
- run函数
- with函数
- apply函数
- also函数
- 标准库函数
- takeIf 与 takeUnless
- 第二阶段重点深入
- Lambda编程
- Lambda成员引用高阶函数
- 高阶函数
- 内联函数
- 泛型
- 泛型的分类
- 泛型约束
- 子类和子类型
- 协变与逆变
- 泛型擦除与实化类型
- 泛型类型参数
- 泛型的背后:类型擦除
- Java为什么无法声明一个泛型数组
- 向后兼容的罪
- 类型擦除的矛盾
- 使用内联函数获取泛型
- 打破泛型不变
- 一个支持协变的List
- 一个支持逆变的Comparator
- 协变和逆变
- 第三阶段难点突破
- 注解和反射
- 声明并应用注解
- DSL
- 协程
- 协程简介
- 协程的基本操作
- 协程取消
- 管道
- 慕课霍丙乾协程笔记
- Kotlin与Java互操作
- 在Kotlin中调用Java
- 在Java中调用Kotlin
- Kotlin与Java中的操作对比
- 第四阶段专题练习
- 朱凯Kotlin知识点总结
- Kotlin 基础
- Kotlin 的变量、函数和类型
- Kotlin 里那些「不是那么写的」
- Kotlin 里那些「更方便的」
- Kotlin 进阶
- Kotlin 的泛型
- Kotlin 的高阶函数、匿名函数和 Lambda 表达式
- Kotlin协程
- 初识
- 进阶
- 深入
- Kotlin 扩展
- 会写「18.dp」只是个入门——Kotlin 的扩展函数和扩展属性(Extension Functions / Properties)
- Kotlin实战-开发Android