——纳兰容若 ·《虞美人》

实际开发中,关于字符串的使用可谓是随处可见,如若你连最基本的操作都不会,那岂不“JJ思密达“?
故而, 在这篇文章中,会对字符串( String )的常用操作做出一个讲解。比如,字符串的截取、查找、获取长度、替换等等…

一、字符串查找

字符串查找功能在实际开发中,只会用到几个简单的函数,这里我只说明几个常用的。

1.1、获取第一个元素

主要包含 first() | firstOrNull() first{} | firstOrNull{} 四个函数

first() | firstOrNull()

  • 作用 : 查找字符串的第一个元素
  • 区别 :若字符串为空串时,前者会抛出 NoSuchElementException 异常 ,后者会返回 null
  • val str = "kotlin very good"

    // 如果字符串为空串时,会抛出NoSuchElementException异常
    str.first()   <=>   str[0]   <=>   str.get(0)

    // 如果字符串为空串时,会返回null
    str.firstOrNull()
    复制代码

    first{} | firstOrNull{}

  • 作用 : 查找等于某一个字符的第一个元素
  • 区别 :未查找到满足条件的元素,前者会抛出 NoSuchElementException 异常 ,后者会返回 null
  • val str = "kotlin very good"

    // 如果未查找到满足条件的元素,会抛出NoSuchElementException异常
    str.first{ it == 'o' } 

    // 如果未查找到满足条件的元素,会返回null
    str.firstOrNull{ it == 'o' } 
    复制代码

    1.2、 获取最后一个元素

    主要包含 first() firstOrNull() first{} firstOrNull{} 四个函数

    last() lastOrNull()

  • 作用 : 查找字符串的最后一个元素
  • 区别 :若字符串为空串时,前者会抛出 NoSuchElementException 异常 ,后者会返回 null
  • val str = "kotlin very good"

    // 如果字符串为空串时,会抛出NoSuchElementException异常
    // 其中 lastIndex 是一个拓展属性,其实现是 length - 1
    str.last()   <==>   str.get(lastIndex)   <==>  str[lastIndex]

    // 如果字符串为空串时,会返回null
    str.lastOrNull()
    复制代码

    last{} lastOrNull{}

  • 作用 : 查找等于某一个字符的最后一个元素
  • 区别 :未查找到满足条件的元素,前者会抛出 NoSuchElementException 异常 ,后者会返回 null
  • val str = "kotlin very good"

    // 如果未查找到满足条件的元素,会抛出NoSuchElementException异常
    // 其实从源码中我们发现其是对原字符串反转之后再进行遍历查找满足条件的元素。这样遍历的次数就减少了
    str.lastit == 'o' } 

    // 如果未查找到满足条件的元素,会返回null
    str.lastOrNull{ it == 'o' } 
    复制代码

    1.3、查找元素

    1.3.2、find{} | findLast{}
    其实查找元素提供了两个高阶函数 find{} findLast{} 。不过其内部都是调用 firstOrNull() lastOrNull() 函数进行处理。这里不多作累述。

    1.3.2、 查找对应元素的下标

  • indexOf() : 查找某一个元素或字符串在原字符串中第一次出现的下标。
  • indexLastOf() : 查找某一个元素或字符串在原字符串中最后一次出现的下标。
  • indexOfFirst{} : 同 indexOf()
  • indexOfLast{} : 同 indexLastOf()
  • val str = "kotlin very good"

    println(str.indexOfFirst { it == 'o' })
    println(str.indexOfLast { it == 'o' })
    println(str.indexOf('o',0))
    println(str.indexOf("very",0))
    println(str.lastIndexOf('o'))
    println(str.lastIndexOf("good"))
    复制代码

    输出结果为:

    1
    14
    1
    7
    14
    12
    复制代码

    二、字符串截取

    如果你有 Java 或者其他语言的编程基础。相信您对字符串的截取应该不会陌生。您可以继续的往下看,就当作是对字符串截取只是的一个巩固。当然,您也可以直接的跳过本节内容,因为在 Kotlin 中,字符串的截取的函数 subString() 是调用了 Java 中的 subString() 函数。

    Kotlin 中除了调用 subString() 函数外,还可以调用 subSequence() 函数,有兴趣的朋友可以去看看源码。

    2.1、 用 subString() 函数截取

    我们看一看 subString() 函数的源码

    @kotlin.internal.InlineOnly
    public inline fun String.substring(startIndex: Int): String = (this as java.lang.String).substring(startIndex)

    @kotlin.internal.InlineOnly
    public inline fun String.substring(startIndex: Int, endIndex: Int): String 
    = (this as java.lang.String).substring(startIndex, endIndex)

    public fun String.substring(range: IntRange): String = substring(range.start, range.endInclusive + 1)
    复制代码

    从以上的源码中我们可以看出, Kotlin 中是使用了 Java 中的 subString() 函数

  • startIndex 参数:截取字符串的开始下标
  • endIndex 参数:截取字符串的结束下标
  • rang 参数,是指一个 IntRang 类型,表示一个范围
  • val str = "Kotlin is a very good programming language"

    println("s = ${str.substring(10)}")  // 当只有开始下标时,结束下标为length - 1
    println(str.substring(0,15))
    println(str.substring(IntRange(0,15)))
    复制代码

    输出结果为:

    a very good programming language
    Kotlin is a ver
    Kotlin is a very
    复制代码
  • 使用 subString(startIndex,endIndex) subString(rang) 时的区别。可以从上边的结果结合源码可以看出来。
  • 切记下标越界的情况。即 StringIndexOutOfBoundsException 异常
  • 2.2、用 subSequence() 函数截取

    Kotlin 中除了使用上面讲解到的使用 subString() 截取字符串外,还可以使用 subSequence() 函数截取。

    我们看一看其源码实现:

    public fun subSequence(startIndex: Int, endIndex: Int): CharSequence

    public fun CharSequence.subSequence(range: IntRange): CharSequence = subSequence(range.start, range.endInclusive + 1)
    复制代码

    从源码中我们可以看出,其大致和 subString() 函数一样,但是其不提供只传递 startIndex 的情况

    val str = "Kotlin is a very good programming language"

    println(str.subSequence(0,15))
    println(str.subSequence(IntRange(0,15)))
    复制代码

    输出结果为:

    Kotlin is a ver
    Kotlin is a very
    复制代码

    三、字符串替换

    同上述字符串截取一样,如果您有编程经验,可跳过此节。不过对于字符串替换功能, Kotlin 除了实现 Java 中的 replace() ha函数外,还提供了另外的 replaceFirst() replaceAfter() replaceBefore() replaceIndent() 、等函数。下面会对这些函数意义进行实例讲解。

    3.1、replace()函数

    replace() 函数提供了4个重载函数。他们能实现不同的功能

    3.1.1、 replace(oldChar,newChar,ignoreCase = false)

    作用 : 把原字符串中的某一个字符全部替换成新的字符。然后返回新的字符串

  • oldChar : 需要替换的字符
  • newChar : 新的字符
  • ignoreCase : 是否引用 Java 中的 replace() 函数。默认值为 false ,即用 Java replace() 函数
  • // 把字符`a`全部替换为`A`
    val str = "Kotlin is a very good programming language"
    println(str.replace('a','A'))
    复制代码

    输出结果为:

    Kotlin is A very good progrAmming lAnguAge
    复制代码

    3.1.2、 replace(oldValue,newValue,ignoreCase = false)

    作用 : 把原字符串中的某一个字符全部替换成新的字符。然后返回新的字符串

  • oldValue : 需要替换的字符串
  • newValue : 新的字符串
  • ignoreCase : 是否引用 Java 中的 replace() 函数。默认值为 false ,即用 Java replace() 函数
  • // 把字符串`Kotlin`替换成字符串`Java`
    val str = "Kotlin is a very good programming language"
    println(str.replace("Kotlin","Java"))
    复制代码

    输出结果为:

    Java is a very good programming language
    复制代码

    3.1.3、 replace(regex,replacement)

    作用 : 根据定义的正则规则去匹配源字符串,把满足规则的字符串替换成新的字符串。

  • regex : 正则表达式
  • replacement : 新的字符串
  • // 正则的规则为检测数字,如果为数字则替换成字符串`kotlin`
    val str = "1234a kotlin 5678 3 is 4"
    println(str.replace(Regex("[0-9]+"),"kotlin"))
    复制代码

    输出结果为:

    kotlina kotlin kotlin kotlin is kotlin
    复制代码

    3.1.4、replace(regex: Regex, noinline transform: (MatchResult) -> CharSequence)

  • 作用 : 根据定义的正则规则去匹配源字符串,把满足规则的字符串通过 transform{} 高阶函数映射的新字符串替换。
  • regex : 正则表达式
  • transform : 高阶函数
  • val str = "1234a kotlin 5678 3 is 4"
    val newStr = str.replace(Regex("[0-9]+"),{"abcd "})
    复制代码

    输出结果为:

    abcd abcd abcd abcd a kotlin abcd abcd abcd abcd  abcd  is abcd
    复制代码

    可以从上述的两个函数中看到两个函数的区别。关于 高阶函数 正则表达式 的知识点可以先自行看资料理解。小生会在后续的章节中补上相关的内容…

    经过上面的 replace() 函数的讲解。并且对几个重载函数进行了分析。相信大家对 replace() 函数中的参数都有大致的了解。并且下面的几个函数也是大致相同的操作。故而下面的几个函数操作,我只会举例说明其作用。关于参数的介绍就不作细究了

    3.2、replaceFirst()

    作用:把满足条件的第一个字符或字符串替换成新的字符或字符串

    val str = "Kotlin is a very good programming language"
    println(str.replaceFirst('a','A'))
    println(str.replaceFirst( "Kotlin","Java"))
    复制代码

    输出结果为:

    Kotlin is A very good programming language
    Java is a very good programming language
    复制代码

    3.3、replaceBefore()

    作用:截取满足条件的第一个字符或字符串后面的字符串,包含满足条件字符或字符串自身,并在其前面加上新的字符串。

    val str = "Kotlin is a very good programming language"
    println(str.replaceBefore('a',"AA"))
    println(str.replaceBefore("Kotlin","Java"))
    复制代码

    输出结果为:

    AAa very good programming language
    JavaKotlin is a very good programming language
    复制代码

    3.4、replaceBeforeLast()

    作用:截取满足条件的最后一个字符或字符串后面的字符串,包含满足条件字符或字符串自身,并在其前面加上新的字符串。

    val str = "Kotlin is a very good programming language"
    println(str.replaceBeforeLast('a',"AA"))
    println(str.replaceBeforeLast("Kotlin","Java"))
    复制代码

    输出结果为:

    AAage
    JavaKotlin is a very good programming language
    复制代码

    3.5、replaceAfter()

    作用:截取满足条件的第一个字符或字符串前面的字符串,包含满足条件字符或字符串自身,并在其后面加上新的字符串。

    val str = "Kotlin is a very good programming language"
    println(str.replaceAfter('a',"AA"))
    println(str.replaceAfter("Kotlin","Java"))
    复制代码

    输出结果为:

    Kotlin is aAA
    KotlinJava
    复制代码

    3.6、replaceAfterLast()

    作用:截取满足条件的最后一个字符或字符串前面的字符串,包含满足条件字符或字符串自身,并在其后面加上新的字符串。

    val str = "Kotlin is a very good programming language"
    println(str.replaceAfterLast('a',"AA"))
    println(str.replaceAfterLast("Kotlin","Java"))
    复制代码

    输出结果为:

    Kotlin is a very good programming languaAA
    KotlinJava
    复制代码

    四、字符串分割

    同上一节一样, Kotlin 除了实现 Java 中的 split() 函数之外,还提供了 splitToSequence() 函数来分割字符串。分割成功后都会返回一个字符串集合用于我们后续操作。

    4.1、 split()

    split() 函数也是提供了 4 个重载函数。其中,用正则表达式为条件分割占用两个。用字符分割占用一个。用字符串分割占用一个。

    4.1.1、使用正则表达式分割

    Kotlin 中使用正则表达式,使用的是 Regex 类,而 Java 中使用正则表达式使用的 Pattern 类。这里分别举例说明

    var str2 = "1 kotlin 2 java 3 Lua 4 JavaScript"

    val list3 = str2.split(Regex("[0-9]+"))
    for (str in list3){
        print("$str \t")
    }

    println()

    val list4 = str2.split(Pattern.compile("[0-9]+"))
    for (str in list4){
        print("$str \t")
    }
    复制代码

    输出结果为:

    kotlin  java  Lua  JavaScript     
    kotlin  java  Lua  JavaScript     
    复制代码

    4.1.2、使用字符或字符串分割

    在实际的项目开发中,还是这种方式用的要多一些。不过这里值得注意的是,不管是用字符分割,还是字符串分割,其都是一个可变参数。即其参数的个数不定。

    val str1 = "Kotlin is a very good programming language"

    val list1 = str1.split(' ')
    for (str in list1){
        print("$str \t")
    }

    println()

    val list2 = str1.split(" ")
    for (str in list2){
        print("$str \t")
    }
    复制代码

    输出结果为:

    Kotlin   is   a   very     good    programming     language
    Kotlin   is   a   very     good    programming     language
    复制代码

    这里举例一个可变参数情况的例子:

    val str3 = "a b c d e f g h 2+3+4+5"
    val list5 = str3.split(' ','+')
    for (str in list5){
        print("$str \t")
    }
    复制代码

    输出结果为:

    a     b   c   d   e   f   g   h   2   3   4   5 
    复制代码

    4.2、 splitToSequence()

    此函数同样可以用字符串或字符去分割,其用法和上述的 split() 函数一样。这里就不多累述了…

    除了上面讲解到的几点外,还有很多常用的处理,比如检测字符串是否为空串,是否为 null ,获取字符串长度,字符串反转,统计,转换字符数组,获取指定下标的字符等等。

    5.1、 获取字符串长度

    Kotlin 中用两种获取字符串长度的方法。其实也是一种而已

  • 直接用 length 属性获取长度
  • count() 函数获取,其实 count() 函数的做法也是返回了 length 长度。
  • val str = "kotlin very good"

    // 1. 直接用length属性获取
    println("str.length => ${str.length}")

    // 2. 用count()函数获取
    println("str.count() => ${str.count()}")
    复制代码

    输出结果为:

    str.length => 16
    str.count() => 16
    复制代码

    这里我们看一看 count() 函数的源码

    /**
     * Returns the length of this char sequence.
     * 其实也就是返回了length属性...
     */

    @kotlin.internal.InlineOnly
    public inline fun CharSequence.count()Int {
        return length
    }
    复制代码

    5.2、统计重复字符

    上面讲到了 count() 函数,是返回了 length 属性获取字符串的长度。其实源码中还提供了一个叫 count{} 的高阶函数,用于统计字符串中重复某个字符的个数。

    /*
      count{}函数源码  
      该函数接受一个`Boolean`类型的`Lambda`表达式。然后循环这个字符串,如果我的条件成立,则变量`count`自增。
      循环完成之后返回重复的个数`count`
     */

    public inline fun CharSequence.count(predicate: (Char) -> Boolean): Int {
        var count = 0
        for (element in thisif (predicate(element)) count++
        return count
    }
    复制代码
    val str = "kotlin very good"
    val count = str.count { it == 'o' }
    println("count : $count")
    复制代码

    输出结果为:

    count : 3
    复制代码

    5.3、 验证字符串

    在实际的开发中,特别是 Android 开发中,会经常遇到验证输入框的内容是否为空串的时候。在 Kotlin 中,和 Java 一样提供了几个处理这种情况的函数。

    下列几个函数都是处理字符串为空串或为空的:

  • isEmpty() : 其源码是判断其 length 是等于 0 ,若等于 0 则返回 true ,反之返回 false 。不能直接用于可空的字符串
  • isNotEmpty() : 其源码是判断其 length 是否大于 0 ,若大于 0 则返回 true ,反之返回 false 。不能直接用于可空的字符串
  • isNullOrEmpty() : 其源码是判断该字符串是否为 null 或者其 length 是否等于 0
  • isBlank() : 其源码是判断其 length 是否等于 0 ,或者判断其包含的空格数是否等于当前的 length 。不能直接用于可空的字符串
  • isNotBlank() : 其源码是对 isBlank() 函数取反。不能直接用于可空的字符串
  • isNotOrBlank() : 其源码判断该字符串是否为 null 。或者调用 isBlank() 函数
  • val str : String? = "kotlin"

    /* 
      可以看出当str为可空变量的时候,isNullOrEmpty()和isNotOrBlank()可以不做直接调用而不做任何处理
      ,而其他的函数则不行
     */

    str?.isEmpty()            //false
    str?.isNotEmpty()         // true
    str.isNullOrEmpty()       //false
    str?.isBlank()            //false
    str?.isNotBlank()         //true
    str.isNullOrBlank()       //false
    复制代码

    5.4、字符串连接

    字符串链接,在 Java 中只能使用 + 来链接,当然除了 StringBuilder、StringBuffer 除外。而在 Kotlin 中除了使用 + 以外,还可以使用 plus() 函数。其接受任意类型。 plus() 函数是一个运算符重载函数。在前面的章节中讲解过了。若你对 Kotlin 中的云素福重载不了解,您可以查看我的另一篇文章: Kotlin——初级篇(五):操作符重载一

    实例讲解:

    val oldStr = "kotlin"
    println(oldStr.plus(" very good"))
    println(oldStr + " very good")
    复制代码

    输出结果为:

    kotlin very good
    kotlin very good
    复制代码

    5.5、字符串反转

    和数组一样,字符串也是可以反转元素的。直接使用 reversed() 函数即可。

    val str = "kotlin"
    println("字符串反转:${str.reversed()}")
    复制代码

    输出结果:

    字符串反转:niltok
    复制代码

    5.6、判断字符串的起始与结尾

    5.6.1、 startsWith()

    作用: 判断其字符串是否由某一个字符或字符串起始。

  • char : 起始字符
  • prefix : 起始字符串
  • ignoreCase : 是否调用 Java 中的此函数。默认为 false
  • startIndex : 开始位置
  •     val str = "kotlin"
        println(str.startsWith('k'))         // 是否有字符`k`起始
        println(str.startsWith("Kot"))       // 是否由字符串`kot`起始
        println(str.startsWith("lin",3))     // 当起始位置为3时,是否由字符串`lin`起始
    复制代码

    输出结果为:

    true
    true
    true
    复制代码

    5.6.2、endsWith()

    作用: 判断其字符串是否由某一个字符或字符串结尾。

  • char : 结尾字符
  • suffix : 结尾字符串
  • ignoreCase : 是否调用 Java 中的此函数。默认为 false
  • val str = "kotlin"
    println(str.endsWith("lin"))  // 是否由字符串`lin`结尾
    println(str.endsWith('n'))    // 是否由字符`n`结尾
    复制代码

    输出结果为:

    true
    true
    复制代码

    在实际开发中,字符串的处理使用的情况是很多的。特别是字符串的验证处理、替换、分割、截取。这也是我把这些知识点整理出来的原因。这些知识点是很基础,但同时也是很常用的。如果您有编程经验的话您就当对字符串的基础知识的巩固。
    关于 kotlin 中字符串的操作就写到这里,其实还有很多功能,虽然在开发中用到的地方不是特别多,但是我们最起码能应该有个了解。有兴趣的朋友可以去看看其源码的实现。

    本文已收录至GitHub: Jetictors/KotlinLearn ,欢迎star

    文章持续更新中,可以微信搜索「J佬杂谈 」第一时间阅读, 大家的三连击是对老J最好的动力了,你确定不来一波吗?

    如果本篇博客有任何错误和建议,欢迎人才们留言

    啊喂,五指菇娘啊,拿着手机扫描一下吧!
    分类:
    Android