[AS3.6.1]Kotlin学习笔记6(操作符,快捷扩展函数)

前言

kotlin学习第六篇文章!
历史文章
[AS3.6.1]Kotlin学习笔记1(基本声明,函数,条件)
[AS3.6.1]Kotlin学习笔记2(常量,数组,修饰符)
[AS3.6.1]Kotlin学习笔记3(简化操作,泛型)
[AS3.6.1]Kotlin学习笔记4(接口,Lambda,协程)
[AS3.6.1]Kotlin学习笔记5(类说明,函数说明)

操作符

kotlin的操作符有非常的多,基本罗列了可用的很多功能。我们这边就看下常用的就好了,更多可以看看这篇文章Kotlin 学习笔记(十二)kotlin中 集合序列使用、操作符汇总、list和sequence比较在操作符汇总中有很多操作符使用。

我们看下常用如下

下标操作类

  • contains —— 判断是否有指定元素
  • elementAt —— 返回对应的元素,越界会抛IndexOutOfBoundsException
  • firstOrNull —— 返回符合条件的第一个元素,没有 返回null
  • lastOrNull —— 返回符合条件的最后一个元素,没有 返回null
  • indexOf —— 返回指定元素的下标,没有 返回-1
  • singleOrNull —— 返回符合条件的单个元素,如有没有符合或超过一个,返回null

判断类

  • any —— 判断集合中 是否有满足条件 的元素
  • all —— 判断集合中的元素 是否都满足条件
  • none —— 判断集合中是否 都不满足条件,是则返回true
  • count —— 查询集合中 满足条件 的 元素个数
  • reduce —— 从 第一项到最后一项进行累计

过滤类

  • filter —— 过滤 掉所有 满足条件 的元素
  • filterNot —— 过滤所有不满足条件的元素
  • filterNotNull —— 过滤NULL
  • take —— 返回前 n 个元素

转换类

  • map —— 转换成另一个集合(与上面我们实现的 convert 方法作用一样);
  • mapIndexed —— 除了转换成另一个集合,还可以拿到Index(下标);
  • mapNotNull —— 执行转换前过滤掉 为 NULL 的元素
  • flatMap —— 自定义逻辑合并两个集合;
  • groupBy —— 按照某个条件分组,返回Map;

排序类

  • reversed —— 反序
  • sorted —— 升序
  • sortedBy —— 自定义排序
  • sortedDescending —— 降序

如果我们想要实现自定义操作符,也是可以的。我们先看下kotlin源码中的操作符是如何编写的

public inline fun  Iterable.forEach(action: (T) -> Unit): Unit {
    for (element in this) action(element)
}

public inline fun  Iterable.reduce(operation: (acc: S, T) -> S): S {
    val iterator = this.iterator()
    if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
    var accumulator: S = iterator.next()
    while (iterator.hasNext()) {
        accumulator = operation(accumulator, iterator.next())
    }
    return accumulator
}

很明显我们可以看到基本都是遍历和循环一下集合数组等,所以我们想要写自定义操作符,只需要做相应的写法就好了。以下是自定义操作符函数,可以将List转换为List

    public inline fun  Iterable.convert(action: (T) -> E): MutableList {
        val list: MutableList = mutableListOf()
        for (element in this) list.add(action(element))
        return list
    }

基于操作符非常的多,这边就只做一个简单说明,实际要使用的时候可以查阅官方资料关键字与操作符

快捷扩展函数

这边的快捷扩展函数是官方为我们提供的常用的友好的扩展函数。

use

我们经常处理流的时候,都需要在操作完成之后关闭流。所以官方为我们加入了一个use的扩展函数,使用如下

    val file: File= File("文件路径")
    try {
        file.bufferedReader().use { 
            ...
        }
    }catch (e: Exception){
        e.printStackTrace()
    }

require、check

我们也常常会判断一个值为空或者是否为真,大小之类的。官方也提供的这类函数,省去了if判断之后在throw异常的操作,使用如下

    val a =10
    require(a > 100){
        "错误提示"
    }
    requireNotNull(a > 5){
        "错误提示"
    }
    check(a > 10){
        "错误提示"
    }
    checkNotNull(a > 5) {
        "错误提示"
    }

这些都是直接抛出异常的。

作用域函数 run, with, let, also, apply

官方提供了好几个作用域函数,那么我们到底应该什么时候使用什么函数呢?我们需要从三个方面来判断使用哪个

  1. 是否是扩展函数
  2. 作用域函数的参数(this、it)
  3. 作用域函数的返回值(调用本身、其他类型即最后一行)

是否是扩展函数 runwith

runwith的使用非常的相似,区别就在于with是普通函数,而run是扩展函数
示例入下

    val name: String? = "ZhangSan"

    with(name){
        val subName = name?.substring(1, 2)
    }

    name?.run {
        val subName = name.substring(1, 2)
    }

我们可以很明显的看到withrun的使用区别。

作用域函数的参数(this、it)runlet

runlet都是扩展函数,但是run作用的参数是this本身而let作用的参数是it
示例入下

    val list: List ?= listOf("1", "2", "3")
    list?.run {
        for (str in this) {
            print("$str ")	//1 2 3 
        }
    }
    list?.let {
        for (str in it) {
            print("$str ")	//1 2 3 
        }
    }
    list?.let { strs ->
        for (str in strs) {
            print("$str ")	//1 2 3 
        }
    }

run对比let好像基本一样,但是letit是可以自定义名称的。

作用域函数的返回值(调用本身、其他类型)alsolet

letalso作用参数都是it,但是返回值确差别很大。also最后返回的是this本身,而let返回的是函数的最后一行.
示例入下

    var name = "hello kotlin"

    name = name.also {
        val a = 1 + 1
        "a = $a"
    }
    println("name = $name")	//name = hello kotlin

    name = name.let {
        val a = 1 + 1
        "a = $a"
    }
    println("name = $name")	//name = a = 2

let最后一行返回的值是可以任意类型的。由于also的返回自身的特性,我们结合其他作用域函数可以实现很多自我操作的情况,示例如下

	//直接实现 file创建
    fun mkDir(path: String){
        File(path).also { it.mkdirs() }
    }

	//直接替换值
    var a = 1;
    var b = 2;
    println("a = $a , b = $b")	//a = 1 , b = 2
    a = b.also { b = a }
    println("a = $a , b = $b")	//a = 2 , b = 1

apply

经过上面三层判断,我们可以了解apply到是一个扩展函数,作用参数是this,返回值也是this
使用示例如下

	fun createInstance(args: Bundle) : MyFragment {
	    val fragment = MyFragment()
	    fragment.arguments = args
	    return fragment
	}
	
	fun createInstance2(args: Bundle)  = MyFragment().apply { arguments = args }

    fun showNext(act: Activity, bundle: Bundle, cls: Class<*>){
        val intent = Intent(act, cls)
        intent.putExtras(bundle)
        act.startActivity(intent)
    }

    fun showNext2(act: Activity, bundle: Bundle, cls: Class<*>){
        act.run { startActivity(Intent(this, cls).apply { putExtras(bundle) }) }
    }

可以看到使用环境也是按需求挺多的。

其他优化

尽量少使用 toLowerCase 和 toUpperCase 方法

    val oldName = "Hi Kotlin"
    val newName = "hi kotlin"
    val result1 = oldName.toLowerCase() == newName.toLowerCase()

    val result2 = oldName.equals(newName, ignoreCase = true)

    println("result1 = $result1")	//result1 = true
    println("result2 = $result2")	//result2 = true

使用kotlin的equals方法中的ignoreCase关键字来实现优化掉一些多余的新增字符串

总结

基础之后的一些便捷方法记录

资料

Kotlin 常用操作符
Kotlin 学习笔记(十二)kotlin中 集合序列使用、操作符汇总、list和sequence比较
Kotlin Primer·第六章·集合泛型与操作符
关键字与操作符
为数不多的人知道的 Kotlin 技巧以及 原理解析
为数不多的人知道的 Kotlin 技巧以及 原理解析(二)

你可能感兴趣的:(程序日记,学习日记)