Kotlin初体验(三)- 字符串 和 容器

字符串

字符串与基本数据类型转换

基本数据类型转String,在上一篇博客已经讲过,调用toString(),反过来,字符串又该如何转换成基本数据类型呢?请看下表

字符串转换为其他数据类型的Kotlin与Java方式对比

字符串转换目标 Kotlin转换方式 Java转换方式
String->Int toInt( ) Integer.parseInt(字符串变量)
String->Long toLong( ) Long.parseLong(字符串变量)
String->Float toFloat( ) Float.parseFloat(字符串变量)
String->Double toDouble( ) Double.parseDouble(字符串变量)
String->Boolean toBoolean( ) Boolean.parseBoolean(字符串变量)
String->Char[ ] toCharArray( ) toCharArray( )

Kotlin方式更加简单,直接“变量.toXXX( )”即可 。

字符串常用方法

当然,转换类型只是字符串最基本方法,还有更多字符串处理的其他方法,例如查找子串,替换子串,截取指定位置的子串,按照特定字符分割子串等。在这方面,Kotlin基本兼容Java的相关方法。对于子串的查找,二者都用indexOf( ),对于截取指定位置子串操作,二者都调用substring( ),替换则为replace( ),按照特定字符分割,二者都调用split ( )。值得注意的是在这些方法中唯一不同的是,split的返回值,Java中split返回值是String[ ],Kotlin中,split方法返回值是String队列,即List<String>
另外在Java中,获取某个位置字符调用str.chatAt(index),Kotlin中直接可以str[index].toString( )

字符串模板及其拼接

我们知道在Java中字符串拼接,一般采用加号(+)强行拼接,或者String.format函数进行格式化。但是使用+ 容易和数值计算的+混淆,而后者格式化需要程序员牢记,如%d,%f,%s,%bd等格式转换符,增加脱发风险。而Kotlin恰如其分的对该痛点进行了优化,何必引入这些令人脱发的转换符呢?直接在字符串中加入“$变量名”即可表示此处引用变量值,岂不妙哉!
直接上代码

        val str: String = "Hello iblade"
        var num: Int = 500
        //拼接字符串直接“str $变量名”,别忘了$前加一个空格
        textView.text = "我拼接内容是 $str"
        //另外先运算,再把运算结果拼接到字符串的情况,可以直接加{ },当然AS会自动生成该括号
        textView.text = "str length = ${str.length}"
        //我想打印$怎么办?转义字符  ${'XXX'}  其中,XXX会被原样输出。
        textView.text = "美元结算为:${'$'}$num"
        //如果只对单个字符做转义的话,还有更简单方式直接反斜杠 \X 
        textView.text = "美元结算为:\$$num"

字符串拼接小结:

  1. 字符串拼接用“$变量名”
  2. 单个字符转义,反斜杠+字符 “ \X ”
  3. 多个字符转义 “ ${ ’ XXX ’ } ”

容器

容器基本操作

与Java类似,Kotlin也拥有三种基本的容器,分别是集合Set,队列List,映射Map,然后每种容器又分为只读可变两种。这是为了判断该容器,是否能进行增,删,改等变更操作。Kotlin在对变量的修改操作很谨慎,每个变量在定义时就必须指定能否修改,比如添加val表示不能修改,只有var时才能修改。容器默认均为只读容器,如需修改该容器,则需要加上Mutable前缀形成新的容器,如MutableList,MutableSet,MutableMap,只用可变容器才能增删改。
Set,List,Map同属于容器,当然也有一些共同方法,如下:

  • isEmpty : 判断该容器是否为空
  • isNotEmpty : 判断该容器是否非空
  • clear :清空该容器
  • contains : 判断容器是否包含指定元素
  • iterator : 获取容器迭代器
  • count : 获取容器元素个数,也可以通过size属性获取

另外,Kotlin允许在声明容器时进行赋值,就像数组那样,这是Java中无法做到的。
不同容器初始化赋值方法分别如下:

Kotlin的容器 容器名称 初始化方法
只读集合 Set setOf
只读队列 List listOf
只读映射 Map mapOf
可变集合 MutableSet mutableSetOf
可变队列 MutableList mutableListOf
可变映射 MutableMap mutableMapOf

例如:

        var season: List<String> = listOf("春", "夏", "秋", "冬")
        var age: MutableList<String> = mutableListOf("1", "2", "3")  

Set/MutableSet

特性:(对应Java中的Set)

  1. 元素无序存储,无法通过下标访问
  2. 元素唯一,不重复,hashcode校验是否相同元素,重复则覆盖

Set默认只读,就不再展开讲了。针对MutableSet研究一下;
Mutable添加的元素,不知道具体位置,所以无法修改,可以用remove删除指定元素。

三种遍历

for-in循环、iterator,forEach
for-in和iterator的用法与java一样,都很简单。重点说说forEach:
前两种遍历均脱胎于Java,代码书写上不够精炼,为了将代码精练到极致,Kotlin创造了forEach方法,明确指定该方法就是要依次遍历容器内元素,forEach采用匿名函数形式,内部使用it代表每个元素。具体看代码

        val topSchool: Set<String> 
        	= setOf("清华大学", "北京大学", "河南工业大学", "河南大学", "南开大学")
       //for-in
        btnClick.setOnClickListener {
            var temp = ""
            //使用for-in语句取出容器中每条记录
            for (item in topSchool) {
                temp = "$temp 校名:$item\n"
            }
            textView.text = "中国TOP${topSchool.size}名校排行榜:\n $temp"
        }
		//iterator
        btnClick.setOnClickListener {
            var temp = ""
            val iterator = topSchool.iterator()
            while (iterator.hasNext()) {
                val item = iterator.next()
                temp = "$temp 校名:$item\n"
            }
            textView.text = "中国TOP${topSchool.size}名校排行榜:\n $temp"
        }
		//forEach
        btnClick.setOnClickListener {
            var temp = ""
            //forEach内部使用it代替每个元素
            topSchool.forEach { temp = "$temp 校名:$it\n" }
            textView.text = "中国TOP${topSchool.size}名校排行榜:\n $temp"
        }
    }

在这里插入图片描述
打印结果:
在这里插入图片描述

Set诸多不足,根本原因是无序,例如一旦添加,无法改值,不能根据位置找元素等。实际开发中,用到Set/MutableSet的机会还是挺少的。

List/MutableList:

list/MutableList 有序有下标,和Java中List一样,使用频率很高,常用方法有:get/set/add/removeAt等;

遍历

list的遍历方法除了上述三种外,多了一种下标循环遍历

        val topUniversity: List<String> = listOf("清华大学", "北京人大学", "河南工业大学", "河南大学", "南开大学")

        btnClick.setOnClickListener {
            var desc = ""
            //indices是队列下标数组
            for (index in topUniversity.indices) {
                val item = topUniversity[index]
                desc = "$desc 校名:$item\n"
            }
            textView.text = "中国TOP${topUniversity.size}名校排行榜:\n $desc"
        }

排序操作:sortBy / sortByDescending (升序/降序)

  • reversed–相反顺序;
  • sorted–自然排序(升序);
  • sortedBy–根据方法处理结果进行自然(升序)排序;
  • sortedDescending–降序排序;
  • sortedByDescending–根据方法处理结果进行降序排序;

        val topUniversity: MutableList<String> = mutableListOf("清华大学", "MIT", "河南工业大学", "河南大学", "南开大学")
        var sortAsc = true

        btnClick.setOnClickListener {
            if (sortAsc) {
                topUniversity.sortBy { it.length }
            } else {
                topUniversity.sortByDescending { it.length }
            }
            var temp = ""
            topUniversity.forEach { temp = "$temp 校名: $it\n" }
            textView.text = "名牌大学TOP${topUniversity.size}按照\"${if (sortAsc) "升序" else "降序"}\"重新排名:\n$temp"

            sortAsc = !sortAsc
        }

在这里插入图片描述在这里插入图片描述

**注意:**新版kotlin需要调用sorted()这样带"ed"后缀的方法才能返回List,而sort()是返回Unit。那么这两种方法还有哪些区别,或者说分别在什么场景下使用?

还是以sort为例,sorted()处理过程中会新建临时的List来保存结果数据,对原来的调用者List不会做任何改变,所以需要将新建的对象返回;而sort()是在原来的List基础上进行元素顺序的调整,不会新建对象,所以不需要返回List。

总数操作

方法作用:

  • any–判断集合中是否有满足条件 的元素;

  • all–判断集合中的元素是否都满足条件;

  • count–查询集合中满足条件的元素个数;

  • fold–在给定初始值的基础上,从第一项到最后一项进行累加;

  • foldRight–在给定初始值的基础上,从最后一下到第一项进行累加,与fold只是的方向不同;

  • forEach–循环遍历元素,元素是it,可对每个元素进行相关操作;

  • forEachIndexed–循环遍历元素,同时得到元素index(下标);

  • max–查询最大的元素,如果没有则返回null;

  • maxBy–获取方法处理后返回结果最大值对应的那个元素的初始值,如果没有则返回null;

  • min–查询最小的元素,如果没有则返回null;

  • minBy–获取方法处理后返回结果最小值对应那个元素的初始值,如果没有则返回null;

  • none–判断集合中是否都不满足条件,是则返回true;

  • reduce–与fold区别在于没有初始值,或者说初始值为0,从第一项到最后一项进行累加;

  • reduceRight–从最后一项到第一项进行累加,与reduce只是方向的不同;

  • sumBy–获取方法处理后返回结果值的总和;

过滤操作:

  • drop–返回去掉前n个元素后的列表;

  • dropWhile–返回从第一项起,去掉满足条件的元素,直到不满足条件的一项为止;

  • dropLastWhile–返回从最后一项起,去掉满足条件的元素,直到不满足条件的一项为止;

  • filter–过滤掉所有不满足条件的元素;

  • filterNot–过滤掉所有满足条件的元素;

  • filterNotNull–过滤掉所有值为null的元素;

  • slice–过滤掉非指定下标的元素,即保留下标对应的元素过滤List中指定下标的元素(比如这里只保留下标为1,3,4的元素),当过滤list中有元素值大于目标List大小时会出现异常;

  • take–返回从第一个开始的n个元素;

  • takeLast–返回从最后一个开始的n个元素;

  • takeWhile–返回不满足条件的下标前面的所有元素的集合;

映射操作:

方法作用:

  • flatMap–合并两个集合,可以在合并的时候对迭代元素值it多想要的操作;

  • groupBy–将集合中的元素按照某个条件分组,返回Map;

  • map–将集合中的元素通过某个方法转换后的结果存到一个集合中;

  • mapIndexed–除了得到转换后的结果,还可以拿到index(下标);

  • mapNotNull–执行方法转换前过滤掉为null的元素;

元素操作:

contains–判断集合中是否有指定元素,有则返回true;

elementAt–查找下标对应的元素,如果下标越界会抛IndexOutOfBoundsException异常;
elementAtOrElse–查找下标对应元素,如果越界会根据方法返回默认值(最大下标经方法后的值);
elementAtOrNull–查找下标对应元素,越界会返回Null;

first–返回符合条件的第一个元素,没有则会抛NoSuchElementException异常;
firstOrNull–返回符合条件的第一个元素,没有返回null;

indexOf–返回指定下标的元素,没有返回-1;
indexOfFirst–返回第一个符合条件的元素下标,没有返回-1;
indexOfLast–返回最后一个符合条件的元素下标,没有返回-1;

last–返回符合条件的最后一个元素,没有则会抛NoSuchElementException异常;
lastIndexOf–返回符合条件的最后一个元素,没有返回-1;
lastOrNull–返回符合条件的最后一个元素,没有返回null;

single–返回符合条件的单个元素,如有没有符合的或符合超过一个分别会抛NoSuchElementException或IllegalArgumentException异常;
singleOrNull–返回符合条件的单个元素,如有没有符合或超过一个,返回null;

可以看到,容易出现异常的操作Kotlin会给出另一个安全调用的替代,如first与firstOrNull。

生产操作:

方法作用:

  • partition–根据判断条件是否成立,拆分成两个Pair;

  • plus–合并两个List,可以用"+"替代;

  • zip–两个集合按照下标组合成一个个的Pair塞到集合中返回;

  • unzip–将包含多个Pair的List转换成含List的Pair;

  • Pair对象的数据组成形式为(first, secord),即Pair(1, 2).first可以取出数据1。

注意:文档和网上一些老的资料还提到了merge操作,编码时提示找不到符号,查资料发现从Kotlin 1.0 Beta 2后的版本开始就弃用了。

Map/MutableMap:

map与Java中类似:
containsKey / containsVaule 用于判断是否包含键或值
初始化赋值时,键值对有两种方式:“键名 to 键值” 和 “Pair(键名,键值)
遍历三种形式类似,需要说明一点是,forEach需要不低于API 24以上版本才支持:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/iblade/article/details/82773680