kotlin基础学习-7(扩展,函数式编程,序列相关)

2022-05-04  本文已影响0人  ftd黑马
//在addExt前加上类. ,这里就是扩展了String类的方法,这个方法是,字符串调用该函数返回该字符串+number个!
fun String.addExt(number:Int) = this + "!".repeat(number)

在main函数中调用
    //因为下面新增了addExt函数,所以字符串都可以调用
    println("abc".addExt(3))
//超类定义扩展函数
fun Any.easyPrint() = println()

在main函数中调用
    //超类定义扩展函数
    1.easyPrint()
    "jljklljkl".easyPrint()
//泛型扩展函数,这种写法非常的常见,在标准库函数中,let,also等都是这样写,使用泛型扩展,谁调用这个函数,T就是谁,并且返回当前的T
fun <T> T.easyPrint2() : T {
    println(this)
    return this
}

在main函数中调用
    //泛型扩展函数
    "asdf".easyPrint2().addExt(2).easyPrint2()
//给String类添加一个扩展属性,这个属性可以统计字符串里有多少个元音字母
val String.numVowel
    get() = count{"aeiou".contains(it)}

在main函数中调用
    "abcdefghijklmn".numVowel.easyPrint2()
//可空类型扩展函数,在扩展函数内解决可能出现的空值问题
fun String?.nullableWithDefault(default: String) = println(this?:default)

在main函数中调用
    val nullable:String?= null
    nullable.nullableWithDefault("abc")
infix fun String?.nullableWithDefault2(default: String) = println(this?:default)

在main函数中调用
    //可空类型扩展函数
    val nullable:String?= null
    nullable.nullableWithDefault("abc")
    //如果函数加了infix,那么上面这个可空类型扩展函数就可以这么写了
    //    mapOf("jack" to 18),map集合的写法点击to看源码,就是用infix关键字修饰
    nullable nullableWithDefault2 "abc"
package com.ftd.extention

//定义扩展文件,扩展函数需要在多个文件里面使用,可以将它定义在单独的文件,然后import
fun <T> Iterable<T>.randomTake() = this.shuffled().first()

在别的文件中调用:

package com.example.myapplication

import com.ftd.extention.randomTake as randomTake2  //这里可以重命名

fun main() {
    //定义扩展文件,扩展函数需要在多个文件里面使用,可以将它定义在单独的文件,然后import
    val list = listOf("jack","tom","jason")
    val set = setOf("java","android","python")

//    list.shuffled().first()
    //使用扩展文件里面的扩展函数
//    list.randomTake()

    //重命名扩展
    list.randomTake2()
}
    //map变换函数会遍历接收者集合,让变换器函数作用于集合里的各个元素,返回结果是包含已修改元素的集合,会作为链上下一个函数的输入。
    val animals = listOf("tiger","cat","dog")
    val babies = animals.map {
        animal -> "A baby $animal"
    }

    //打印可以看到,原始集合并没有被修改,map变换函数和自己定义的变化器函数做完事情后返回的是一个新集合
    println(animals)
    println(babies)

    //map返回的集合中的元素个数和输入集合必须一样,不过,返回的新集合的里的元素可以是不同类型的
    val animalLength = animals.map { it.length }
    println(animalLength)

    //flatmap函数操作一个集合的集合,将其中多个集合的元素合并后返回一个包含所有元素的单一集合
    val list = listOf(listOf(1,2,3), listOf(4,5,6)).flatMap { it }
    println(list)//这里的打印结果是[1,2,3,4,5,6]

2.过滤函数filter
过滤是函数式编程的第二大类函数,过滤函数接收一个predicate函数,用它按给定条件检查接收者集合里的元素并给出true或者false的判定。
如果返回true,受检元素就会添加到过滤函数返回的新的集合里,如果是false,就会从新集合里移除。

    //过滤集合里含有"J"的元素
    val names = listOf("Jack","Rose","Jimmy","Tom")
    val jNames= names.filter { it.contains("J") }
    println(jNames)  // 这里打印的是[Jack, Jimmy]
    
    //Demo,组合使用map和filter找质数(只能被1和自身整除)
    val numbers = listOf(4,22,7,39,53,11,55)
    val numbersZhi = numbers.filter {
        //这里的number就是集合里的每一个值,这里的第一个it指的是(2到nunber中的每一个值),第二个it指的是所有number取模后的值
            number ->
        (2 until number).map { number % it }.none { it == 0 }
    }
    println(numbersZhi)

3.合并函数
合并是函数式编程的第三大类函数,合并函数能将不同不同的集合合并成一个新集合,但是和flatmap不一样。
例如zip和fold

    //zip合并函数来合并两个集合,返回一个包含键值对的新集合
    val employee = listOf("jack","tom","rose")
    val sizes = listOf(15,20,40)
    val toMap = employee.zip(sizes).toMap()
    println(toMap["rose"])

    //fold函数用来合并值,这个合并函数接收一个初始的值,随后会根据匿名函数的结果更新
    val fold = listOf(1, 2, 3, 4).fold(0) { total, number ->
        total + number * 3
    }
    println(fold) // 这里的值 = 0+1*3 + 2*3 + 3*3 + 4*3
package com.example.myapplication

/**
 *
 * list,set,map集合类型,这几个集合类型统称为及早集合,这些集合的任何一个实例在创建后,它要包含的元素都会被加入并且允许访问。
 * 对应及早集合,kotlin还有另外一类集合:惰性集合。类似于类的惰性初始化,惰性集合类型的性能表现优异,尤其是用于包含大量元素的集合时,因为集合元素是按需产生的
 *
 *
 *
 *
 * 序列
 * kotlin有个内置惰性集合类型叫序列(Sequence),序列不会索引排序它的内容,也不记录元素数目。
 * 在使用一个序列时,序列里的值可能由无限多,因为某个数据源能产生无限多个元素。
 *
 *
 */


fun Int.isPrime():Boolean{
    (2 until this).map {
        if (this % it == 0){
            return false
        }
    }
    return true
}


fun main() {

    //demo,假设想产生头1000个质数。

    //针对这个需求,我们并不知道1000个质数到哪里,所以假设0-5000里就包含1000个质数。
    val take = (2..5000).toList().filter { it.isPrime() }.take(1000)
    println(take.size) // 但是此时打印结果是669,不够1000个,所以这种写法还需要加while判断

    //使用序列,这里的链式调用执行顺序应该不是顺序执行的,因为这个generateSequence方法和take方法都是Sequence重写过的,内部肯定是有关联。
    val sequenceTake = generateSequence(2) { value ->
        value + 1
    }.filter { it.isPrime() }.take(1000)
    println(sequenceTake.toList().size)//此时执行结果就是1000
}
上一篇下一篇

猜你喜欢

热点阅读