Kotlin 全部基础

IDEA

Kotlin 提供了很多便利,简化了java很多模式化代码。有人说可读性相对较差,习惯之后,会觉得Java不好读。比如:中文思维会觉得英语很难理解,相反而至。每个都要敲代码,磨刀不误砍柴工。泛型如果用好还是有难度的。kt 会越来月流行,不是因为它很强大,而是谷歌在推kotlin,没办法。就说AS 和 eslipse 哪个会一定更好用,并没有。越来越多是kotlin的支持,人世有代谢往来成古今江山留胜迹,我辈复登临。kotlin比java更灵活,移动端不需要那么多并发量。kotlin更像js代码。蹭java 的热度,有有自己的语言,有话语权。移动端开发和前端开发将会有越来越多共同的技术,提升开发效率,降低成本,大势所趋,界面用户体验上的逻辑。新技术出来,天然的抵触,不断的调整心态,新的技术去了解,动向,kotlin 大势所趋,必须学。IT行业,不断有年轻人进入的行业,我们要追随年轻人的脚步。在算法中,函数编程用的比较多。kotlin最大的好处就是支持kotlin和java混编。
直接上项目,用到的知识点只是40%,

1.SHIFT 两下,show kotlin Bytecode

2.kotlin可以使用特殊字符命名函数名,使用反引号括住函数名避免冲突

print(ere("jjj"))
private fun `ere`(name: String, age: Int = 2) {
    print(name + age)
}

3.匿名函数(函数式编程很流行,应用很广泛)

val total:Int="Mississippo".count()
val totals:Int="Mississippo".count { letter -> letter == 's' }
print(total) 11
print(totals) 4

匿名函数不需要return关键字返回数据,会自动返回最后一行语句的结果

//变量的类型是个匿名函数,无参,返回值是String
val result: () -> String
result = {
    val name = "aaaaa"
    "$name"
}
//声明的时候赋值
val result: () -> String = {
     val name = "aaaaa"
     "$name"
}

val result: (Int) -> String = { age ->
     val name = "aaaaa"
    "$name $age"
}
val result: (Int) -> String = {
     val name = "aaaaa"
    "$name $it"
}
//类型推断
val result  = { age:Int ->
    val name = "aaaaa"
    "$name $age"
}
print(result(5)) aaaaa 5

4.IDEA 设置Kotlin 自动类型推断后的类型

在这里插入图片描述
Kotlin 全部基础_第1张图片

5.定义参数是函数的函数


//eg2
showOnBoard("苹果") { goodsName: String, hour: Int ->
    "$goodsName$hour"
}
fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String) {
    val hour = (1..24).shuffled().last()
    print(getDiscountWords(goodsName, hour))
}

6.函数内联即预编译指令,宏定义==宏替换

val getDiscountWords = { goodsName: String, hour: Int ->
   "$goodsName$hour"
}
showOnBoard("苹果", getDiscountWords)
inline fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String) {
    val hour = (1..24).shuffled().last()
    print(getDiscountWords(goodsName, hour))
}

7.函数引用(lambda可替换)

 showOnBoard("苹果", ::getDiscountWords)
 fun getDiscountWords(goodsName: String, hour: Int): String {
    return "$goodsName$hour"
}

fun showOnBoard(goodsName: String, getDiscountWords: (String, Int) -> String) {
    val hour = (1..24).shuffled().last()
    print(getDiscountWords(goodsName, hour))
}

8.函数类型作为返回类型

//eg1
getFullName("aa", result = {
  print(it)
})
getFullName("aa")  {
  print(it)
}
fun getFullName(name: String, result: (count: Int) -> Unit) {
  result.invoke(name.count())
}

9.kotlin传递函数=java传递接口

public class aaa {
    public static void main(String[] args) {
        getFullName("aa", new Result() {
            @Override
            public void getResult(int count) {
                System.out.println(count);
            }
        });
    }
    public  interface Result{
        void getResult(int count);
    }
    public static  void getFullName(String name,Result result) {
        result.getResult(name.length());

    }
}

10.kotlin中lambda就是闭包,作用域、函数式编程风格

11.字符串操作

substring

const val NAME = "Jimmy's friend"
var index = NAME.indexOf('\'')
// var str = NAME.substring(0, index)
var str = NAME.substring(0 until index)
print(str) Jimmy

split 返回list集合数据,list集合支持 解构语法特性 ,其常用简化变量的赋值

const val NAME = "Jimmy,Jim,Bob"
val str =NAME.split(",")
var (one:String,two:String,three:String) =NAME.split(",")
println(str) [Jimmy, Jim, Bob]
println("$one $two $three") Jimmy Jim Bob
//跳过某个值,不会赋值,提高代码运行效率
val list = mutableListOf<String>("aa", "bb", "cc")
val (one: String, _: String, three: String) = list
print("$one $three") aa cc

replace 比java更加强大

const val NAME = "The people's republic China."
fun main() {
   val str=NAME.replace(Regex("[ae]")){
        when (it.value){
            "a"->"8"
            "e"->"6"
            else -> it.value
        }
    }
    println(str) Th6 p6opl6's r6public Chin8.
}

字符串比较 (内存分配) , == 检查两个字符串中的字符是否匹配,(相当于java中的equals); === 检查两个变量是否指向内存堆上同一对象相当于java中的==)

val str1="aa"
val str2="aa"
println(str1==str2) true
println(str1===str2) true
  
val str1="Aa"
val str2="aa".capitalize()
println(str1==str2) true
println(str1===str2) false

double 转int,double 格式化

//保留两位小数 ,四舍五入
val aa = 200.28212
print( "%.2f".format(aa))

12.标准函数 apply let run(可执行引用函数,链式调用) with(一般不用) alse takeIf

let

fun formatGreeting(guestName: String?): String {
    return guestName?.let { "Welcome,$it" } ?: "What's your name?"
}

print(formatGreeting(null))  What's your name?

run(可执行引用函数,链式调用)

var file = File("D://demo//111//readme.txt")
val result = file.run { readText().contains("great") }
print(result) true

fun isLong(name: String) = name.length >= 10
fun showMessage(isLong: Boolean): String {
    return if (isLong) {
        "Name is too long"
    } else {
        "Please rename"
    }
}
"D://demo//111//readme.txt".run(::isLong).run(::showMessage).run(::print)

run 和with 传参方式不一样

val result = "aaaaaa".run { length > 3 }

val result = with("aaaaaa"){
  length > 3
}

alse (我也)返回接收者对象

var fileContents: List<String>
File("D://demo//111//readme.txt")
        .also { println(it.name) }
        .also { fileContents = it.readLines() }
println(fileContents)

readme.txt
[great good]

takeif 如果需要判断某个条件是否满足,再决定是否可以赋值变量或者执行某项任务

val result=  File("D://demo//111//readme.txt")
     .takeIf { it.exists() && it.canRead() }
        ?.readText()
println(result) great good
//不存在
val result=  File("E://demo//111//readme.txt")
     .takeIf { it.exists() && it.canRead() }
        ?.readText()
println(result) null

13.list set

list 通过安全索引函数 获取元素

val list = listOf<String>("aa", "bb", "cc")
println(list.getOrElse(3) { "unknow" })   unknow
println(list.getOrNull(3) ?: "unknow")    unknow

mutable 函数

    val list = mutableListOf<String>("aa", "bb", "cc")
    //运算符重载
    // list.add("dd")
    list += "dd"
    //list.remove("dd")
    list -= "dd"
    //如果此值符合条件,则移除
    list.removeIf { it.contains("aa") }
    //可变和不变相互转换
    list.toList().toMutableList()

list 索引遍历

   list.forEachIndexed { index, s ->  }

set 不可重复,elementAt,其余的都和list用户一致

val set = setOf<String>("aa", "bb")
print(set.elementAt(0))

list 转set 去除重复元素 去重

val list = listOf<String>("aa", "bb","bb")
//print(list.toSet().toList())
//快捷函数
print(list.distinct())

数组类型提供各种array 是引用类型,最终编译成java基本数据类型

map,其它操作写法和list大概一致,to 相当于Pair() 函数

 val map = mapOf("aa" to 20, "bb" to 30)
 mapOf(Pair("aa", 20), Pair("bb", 30))
 println(map["aa"])  20
 println(map.getValue("aa"))  20
 println(map.getOrElse("cc"){"qq"}) qq
 println(map.getOrDefault("cc",0)) 0

map 遍历

 val map = mapOf("aa" to 20, "bb" to 30)
 map.forEach {
        println("${it.key},${it.value}")
    }
 map.forEach { (key: String, value: Int) ->
        println("$key,$value")
    }

map 添加元素 getOrPut

    val map = mutableMapOf("aa" to 20, "bb" to 30)
    map += "cc" to 40
    map["cc"] = 40
    //如果没有则增加
    map.getOrPut("dd") { 50 }
    println(map)

14.kotlin class 类自动生成get/set方法

field 覆盖get、set

class Player {
    var name: String = "j a ck"
    get() = field.capitalize()
    set(value) {
        //去掉前后空格
        field=value.trim()
    }
}

fun main() {
    var p=Player()
    println(p.name)
    p.name="  tom "
    println(p.name)
}

15.初始化

主构造函数

import kotlin.math.absoluteValue

class Player(_name: String, _age: Int) {
    //临时变量只用一次的用下划线
    //get和set紧跟属性,private说明name只读不可以改变
    var name = _name
        get() = field.capitalize()
        private set(value) {
            field = value.trim()
        }
    var age = _age
        get() = field.absoluteValue
        set(value) {
            field = field.absoluteValue
        }
}

fun main() {
    val p=Player("Tom", 30)

}

在主构造函数里定义属性

class Player(_name: String, var age: Int) {
    //临时变量只用一次的用下划线
    //get和set紧跟属性,private说明name只读不可以改变
    var name = _name
        get() = field.capitalize()
        private set(value) {
            field = value.trim()
        }
}

fun main() {
    val p=Player("Tom", 30)

}

次构造函数 constructor

class Player(_name: String, var age: Int) {
    //临时变量只用一次的用下划线
    //get和set紧跟属性,private说明name只读不可以改变
    var name = _name
        get() = field.capitalize()
        private set(value) {
            field = value.trim()
        }
    constructor(name:String):this(name,100){
        this.name=name.toUpperCase()
    }
}

初始化块 init { }

init {
        require(age>10){"age must be positive"}
    }
val p=Player("Tom",9)

在这里插入图片描述初始化顺序
1.著构造函数离声明的属性
2.类级别的属性赋值
3.init初始化块里的属性赋值和函数调用
4.此构造函数里的属性赋值和函数调用
Kotlin 全部基础_第2张图片
延迟初始化 lateinit,用它的时候再初始化

fun main() {
    var user = User()
  //  user.ready()
    user.battle()
}

class User {
    lateinit var equipment: String
    fun ready() {
        equipment = "knife"
    }

    fun battle() {
   		 //健壮的语言
        if (::equipment.isInitialized)
            println(equipment)
    }
}

惰性初始化 by lazy 延迟记载

fun main() {
    var user = User()
    Thread.sleep(3000)
    user.config
}

class User {
    //懒汉式
    val config by lazy { loadConfig() }
    //饿汉式,一上来就记载
    //val config =loadConfig()
    private fun loadConfig(): String {
        println("loading...")
        return "xxx"
    }
}

初始化陷阱1-按照顺序来编译,顺序不能写反

class User {
    val blood = 100

    init {
        val bloodBonus = blood.times(4)
    }
}

初始化陷阱2-按照顺序来编译,顺序不能写反

class User {
    val name: String
    private fun firstLetter() = name[0]

    init {
      //一下两个顺序不能反
        name = "Jack"
        println(firstLetter())
    }
}

16.继承

如果继承类,就要用open来修饰;如果子类需要覆盖父类函数,也需要open来修饰

open class Product(val name:String){
	open fun load()="Nothing.."
}
class AA:Product("aa"){
	override fun load()="xxxxx......"
}
fun main(){
	val p:Product=AA()
	println(p.load())
	//类型检测 is
	println(p is Product)

}

智能类型转换 as,转一次则后面可以直接使用

Any 超类,任意类型 都是Any类 ,Kotlin的跨平台比java更好

object 关键字
单例对象:防止浪费资源;方便管理状态,因为只有一份。

//单例对象
object ApplicationConfig{
	
}
//打印同一个对象
print(ApplicationConfig)
print(ApplicationConfig)

伴生对象 companion

open class configMap{
	companion object{
		private const val PATH="xxxx"
		 fun load()=File(PATH).readBytes()
	}
}
fun main(){
	//比javastatic更加人性化,不调用,则不执行
	ConfigMap.load()
}

嵌套类

class Player2{
	class Equipment(var name:String){
		fun show=println("equipmeng:$ name")
	}
}
fun main(){
	Player2.Equipment("knife").show()
}

数据类 data 专门存数据的类 ,提供 toString / copy(new了新对象,陷阱:不用次构造) / 解构语法

data class Coordinate(var x:Int,var y:Int){
	val isInBounds= x>0
}
fun main(){
	//比较属性的值
	println(Coordinate(10,20)==Coordinate(10,20)) true
}

解构声明

//必须以下写法
class PlayerScore(val experience:Int,val level:Int){
	operator fun component1()=experience
	operator fun component1()=level
}
fun main(){
	val(x,y)=PlayerScore(10,20)
	print("$x $y")
}

//数据类支持解构语法
data class PlayerScore(val experience:Int,val level:Int)
fun main(){
	val(x,y)=PlayerScore(10,20)
	print("$x $y")
}

运算符重载

data class PlayerScore(val x:Int,val y:Int){
	operator fun plus(other:PlayerScore)=PlayerScore(x+other.x,y+other.y)
}
fun main(){
	val a=PlayerScore(10,20)
	val b=PlayerScore(10,20)
	println(a+b)
}

枚举类 特殊类 可以定义函数

enum class Direction(private val score:PlayerScore){
	EAST(PlayerScore(1,2)),
	WEST(PlayerScore(3,2);
	fun updateScore(two:PlayerScore)=PlayerScore(two.x+score.x , two.y+score.y)
}
fun main(){
	print(Direction.EAST) EAST
	print(Direction.EAST.updateScore(PlayerScore(10,10)))  PlayerScore(x=11,12)
}

代数数据类型 ADT 条件固定,else省略

enum class Direction{
	EAST,
	WEST;
}
class DD(var a:Direction){
	fun check():String{
		retrun when(a){
			Direction.EAST ->"东"
			Direction.WEST ->"西"
		}
	}
}

密封类 sealed 里面包含很多类,遇到太复杂的枚举(某个状态需要又个属性 ),则衍生出密封类

enum class Direction{
	object EAST:Direction(),
	class WEST( val str:String):Direction();
}
class DD(var a:Direction){
	fun check():String{
		retrun when(a){
			is Direction.EAST ->"东"
			is Direction.WEST ->"西${t(his.a as WEST).str}"
		}
	}
}

17.接口(一般提供功能,90%只提供函数声明)

interface 默认open,实现使用overrided,默认实现

interface Movable{
	val maxSpeed:Int
			get()=(1..500).shuffled().last()
	var wheels:Int
	fun move(movable:Movable):String
}
class Car(name:String,override var wheels:Int=4):Movable{
	override var maxSpeed:Int
			get()=super.maxSpeed
			set(value){}
	override fun move(movable:Movable):String{
	}
}

抽象类 abstract (和Java一样):既可以有实现的函数也可以有没实现的函数
java多重继承是通过实现接口,再继承;

abstract class Gun(val range:Int){
    abstract  fun pullTrigger():String
}
class  AK47(val price:Int):Gun(50){
    override fun pullTrigger(): String {
        TODO("Not yet implemented")
    }
}`在这里插入代码片`

18.泛型

模板代码放在父类泛型就可以搞定了
泛型 T是Type的简写

class MagicBox<T>(item: T) {
    private var subject: T = item
}
class Boy(val name:String,val age:Int)
class Dog(val weight:Int)
fun main() {
  val box1=MagicBox(Boy("Tom",10))
}

泛型函数

class MagicBox<T>(item: T) {
    private var subject: T = item
    var avaliable = false
    //泛型函数
    fun fetch(): T? {
        return subject.takeIf { avaliable }
    }
}

class Boy(val name: String, val age: Int)

fun main() {
    val box1 = MagicBox(Boy("Tom", 10))
    box1.avaliable=true
    box1.fetch()?.run {
        //run 返回lamble 的执行结果
        print("you find $name")
    }
}

多泛型参数 R 是return的缩写 ,泛型用好不容易

class MagicBox<T>(item: T) {
    private var subject: T = item
    var avaliable = false

    //泛型函数
    fun fetch(): T? {
        return subject.takeIf { avaliable }
    }
    //魔盒放的是男孩,取出来把男孩变成男人;把元素进行修改
    fun <R> fetch(subjectMethod: (T) -> R): R? {
        return subjectMethod(subject).takeIf { avaliable }
    }
    //运算符重载
    operator fun get(index: Int): T? = subject[index]?.takeIf { avaliable }

}

class Boy(val name: String, val age: Int)
class Man(val name: String, val age: Int)
fun main() {
    val box1 = MagicBox(Boy("Tom", 10))
    box1.avaliable = true
    val man= box1.fetch {
        Man(it.name,it.age.plus(15))
    }
}

19.为什么使用 in & out?

如果能使用这些高级特性,说明很牛批了

子类泛型对象可以赋值给父类泛型对象,用out
父类泛型对象可以赋值给子类泛型对象,用in
Kotlin 全部基础_第3张图片

out(协变)kotlin特有的,泛型类型作为函数的返回
in(逆变)kotlin特有的,
invariant(不变)kotlin特有的,



interface Production<out T> {
    fun product(): T
}

interface Consumer<in T> {
    fun consumer(item: T)
}

interface ProductConsumer<T> {
    fun product(): T
    fun consumer(item: T)
}

open class Food
open class FastFood : Food()
class Burger : FastFood()

//生产者
//食品商店
class FoodStore : Production<Food> {
    override fun product(): Food {
        print("Product Food")
        return Food()
    }
}

//快餐商店
class FastStore : Production<FastFood> {
    override fun product(): FastFood {
        print("Product Fast")
        return FastFood()
    }
}

//汉堡商店
class BurgerStore : Production<Burger> {
    override fun product(): Burger {
        print("Product Burger")
        return Burger()
    }
}
//消费者
class Everybody:Consumer<Food>{
    override fun consumer(item: Food) {
        print("eat food")
    }
}
class ModernPeople:Consumer<FastFood>{
    override fun consumer(item: FastFood) {
        print("eat FastFood")
    }
}
class American:Consumer<Burger>{
    override fun consumer(item: Burger) {
        print("eat Burger")
    }
}
fun main() {
    //赋值
    //子类泛型对象可以赋值给父类泛型对象,用out
    val production1: Production<Food> = FoodStore()
    println(production1.product())
    val production2: Production<Food> = FastStore()
    val production3: Production<Food> = BurgerStore()

    //父类泛型对象可以赋值给子类泛型对象,用in ,Everybody的泛型对象类型是Food,Food是Burger的父类
    val consumer1:Consumer<Burger> =Everybody()
    val consumer2:Consumer<Burger> =ModernPeople()
    val consumer3:Consumer<Burger> =American()
}

20.reified :和 inline(替换) 一起使用

如果你想知道某个泛型参数具体是 什么类型,reified关键字可以帮助你检查泛型参数类型。kotlin不允许对泛型参数T做类型检查,因为泛型参数类型会被类型擦除。

open class Human(val age: Int)
class Boy(val name: String, age: Int) : Human(age)
class Man(val name: String, age: Int) : Human(age) {
    override fun toString(): String {
        return "Man(name=$name,age=$age)"
    }
}

class MagicBox2<T : Human>() {
    //随机生成一个对象,如果不是指定对象,就通过backup生成一个对象
    //kotlin 不允许泛型作为类型检查,除非 inline fun <reified T>
    inline fun <reified T> randomOrBackUp(backup: () -> T): T {
        val items = listOf(Boy("Jack", 10), Man("Tom", 30))
        val random = items.shuffled().first()
        return if (random is T) {
            random
        } else {
            backup()
        }
    }
}

fun main() {
    
    val box1: MagicBox2<Man> = MagicBox2()
    val subject: Man = box1.randomOrBackUp {
        Man("Bob", 40)
    }
    println(subject)
    //随机输出
    //Man(name=Tom,age=30)
    //Man(name=Bob,age=40)

}

21.定义扩展函数

扩展可以在不直接修改类定义的情况下增加类的功能

fun String.addExt(amount: Int = 1): String {
  return  this + "!".repeat(amount)
}
fun String.addExt(amount: Int = 1)= this + "!".repeat(amount)

println("abc".addExt(2)) abc!!

链式调用

fun Any.easyPrint(): Any {
    println(this)
    return this
}

fun String.addExt(amount: Int = 1) = this + "!".repeat(amount)

( "abc".easyPrint() as String).addExt(2).easyPrint()

//输出:
abc
abc!!

超类上定义扩展函数-细思极恐

泛型扩展函数(使用范围更广)

标准函数和泛型扩展函数

fun <T> T.easyPrint(): T {
    println(this)
    return this
}

fun String.addExt(amount: Int = 1) = this + "!".repeat(amount)

( "abc".easyPrint() as String).addExt(2).easyPrint()

//输出:
abc
abc!!

扩展属性

//统计有多少个元音字母
val String.numVowels
        get() = count { "aeiou".contains(it) }
 println("aaa".numVowels) 3

可空类扩展 infix

函数式编程带来的好处

fun String?.printDefault(default:String)= print(this?:default)

val aa:String?=null
aa.printDefault("11111") 11111
infix  fun String?.printDefault(default:String)= print(this?:default)

val aa:String?=null
aa printDefault "abc"

定义扩展文件

package extension

fun<T> Iterable<T>.randomTake():T=this.shuffled().first()

使用

import extension.randomTake

fun main(){
    list.randomTake()
}

重命名扩展

import extension.randomTake as APPLE
list.APPLE()

Kotlin 全部基础_第4张图片
标准库中的扩展函数

通常以s结尾 如:Sequences.kt Rangs.kt Maps.kt

22.带接收者的函数字面量 T.() -> Unit

apply 函数如果做到支持接收者对象的隐式调用的。T.() 泛型类型的匿名函数

使用泛型类型匿名函数内部this指向泛型类型的对象,调用它的隐私调用

import java.io.File

//扩展函数(count()=this.count() 隐式调用)
fun String.addExt(amount: Int = 1) = this + "!".repeat(count())

//泛型扩展函数
fun <T> T.easyPrint():Unit = print(this)

//为什么要传入泛型的扩展函数、而不是普通的匿名函数
// T.() ->Unit 扩展函数也可以是匿名函数,匿名函数也可以是扩展韩式
//匿名函数内部this指向一个File对象,隐式调用
//扩展函数自带了接收者对象的this隐式调用
//为什么是泛型的扩展函数

public inline fun <T> T.apply(block: T.() -> Unit): T {
    block()
    return this
}
fun main() {
    val file = File("xx").apply {
        //file 隐式调用
        setReadable(true)
    }

}

// fix 等于 匿名函数 () -> Unit
fun foSomething(fix: () -> Unit) {

}

不是泛型扩展函数,比如以下只支持FIle扩展函数

public inline fun <File> File.apply(block: File.() -> Unit): File {
    block()
    return this
}
fun main() {
    val file = File("xx").apply {
        //file 隐式调用
        setReadable(true)
    }

}
 //分解一下
    //1.定义一个扩展函数
    fun File.ext(): Unit {
        setReadable(true)
    }
    //2.给block变量赋值
    val block = File::ext
    //3.传入apply函数
    File("xx").apply { block }

23.领域特定语言 DSL 暴露接受者的函数和特性

24.函数式编程,未来的趋势

范式:套路或者习惯
函数式编程 在学术;高阶函数,以函数为参数或返回函数;

函数类别(由三大类函数构成)
变换transform 过滤 filter 合并combine;针对集合数据类型,目标是产生一个最终结果;

新技术出来,天然的抵触,不断的调整心态,新的技术去了解,动向,kotlin 大势所趋,必须学。
IT行业,不断有年轻人进入的行业,我们要追随年轻人的脚步。
1.激进派2.顽固派

25.变换transform

最常用的:map flatmap(操作集合的集合,多个集合中元素合并,返回一个集合)
变量不用变来变去

 val list = listOf("aa", "bb")
    list.map { item -> "A baby $item" }
        .map { it -> it.length > 1 }
  print(list)
 val list = listOf(listOf(1, 2, 3), listOf(4, 5, 6))
 val result = list.flatMap { it }
 println(result) [1, 2, 3, 4, 5, 6]

25.过滤 filter

过滤函数接收一个predicate 函数

过滤集合中元素含有"J"字母的元素

  val result=list.filter { it.contains("J") }
    print(result)  ["Jack", "Jime"]

26. flatmap 和filter 组合使用

找包含red的

  val list = listOf(
        listOf("red apple", "green apple", "blue apple"),
        listOf("red fish", "blue fish"),
        listOf("yellow banana", "teal banana")
    )
  val result = list.flatMap { it.filter { it.contains("red") } }
  print(result) ["red apple",red fish"]

找素数,none所有的不能为0

 val number = listOf(7, 4, 8, 4, 3, 22, 18, 11)
 val result = number.filter { number -> (2..number).map { number % it }.none { it == 0 } }
 print(result) [7,3,11]

27.合并combine

合并函数:将不同的集合合并成一个新的集合

zip:合并两个集合,返回一个包含键值对的新集合

 val employee = listOf("Jack", "Jason", "Tomy")
 val ages = listOf(10, 20, 30)

 val employeeAges = employee.zip(ages).toMap()
 print(employeeAges["Jack"]) 10

fold 接受一个初始累加器值,随后根据匿名函数的结果更新;initial 初始累加器的值

遍历一个集合元素,将每个元素乘以3,然后累加

val foldedValue = listOf(1, 2, 3, 4).fold(initial = 0) { accmulator: Int, number: Int ->
        println("$accmulator")
        accmulator + number * 3
    }
    println("$foldedValue")
    //输出结果
    0
    3
    9
    18
    30

28.为什么要使用函数编程

  • 累加变量都是隐式调用
  • 函数运算结果会自动赋值给累加变量,降低了代码出错的机会
  • 执行新任务的函数很容易添加到函数调用链上,因为他们都兼容Iterable类型
  • 可读性更高
    java写法
        List shirtsSize = Arrays.asList("large", "x-large", "medium");
        Map employeesShirtSizes = new HashMap<>();
        for (int i = 0; i < employees.size(); i++) {
            employeesShirtSizes.put(employees.get(i), shirtsSize.get(i));
        }
        List formattedList = new ArrayList<>();
        for (Map.Entry entry : employeesShirtSizes.entrySet()) {
            formattedList.add(String.format("$s,shirt size :$s", entry.getKey(), entry.getValue()));
        }
        System.out.println(formattedList);

        //输出结果
        [Jason,shirt size:x=large,Jack,shirt zie:large,Tomy,shirt zie:medium]

kotlin 写法

  val employees = listOf("Jack", "Jason", "Tomy")
    val shirtsSize = listOf("large", "x-large", "medium")
    val employeesShirtSizes = employees.zip(shirtsSize).toMap()
    val list = employeesShirtSizes.map { "${it.key},shirt size:${it.value}" }
    println(list)

29.序列 Sequence generateSequence

内置惰性集合类型,序列里的值可能有无限多

generateSequence
产生头1000个素数

普通方法

//产生头1000个素数
//有1000个数据的集合
val toList=(1..5000).toList().filter{it.isPrime()}.take(1000)

println(toList.size) 570

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

使用序列查找素数

//从2开始
val oneTousandPrimes:Sequence<Int> = generateSequence(2){value ->
	value + 1
}.filter{it.isPrime()}.take(1000)
println(oneTousandPrimes.toList().size) 1000

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

30. kotlin 和 java 互操作性 可空性

注解@NotNull 一定不为空
注解@Nullable 可能为空

public class Jhava{
	@NotNull
	public String utterCreeting(){
		return "HELLOW";
	}
	@Nullable
	public String determin(){
		return null;
	}
	private int hitPoints=12312
	public String getHitPoints(){
		return hitPoints;
	}
	public void setHitPoints(int hitPoints){
		this.hitPoints=hitPoints;
	}
}

String! 平台类型

fun main(){
	val adversary=Jhave()
	println(adversary.utterCreeting()) HELLOW
	val level:String!=adversary.determin() 没报错
	adversary.determin().toLowerCase() 空指针异常
	level?.toLowerCase() 没报错
}

类型映射
最后都会变成java 类型

31. kotlin 和 java 属性、异常互操作性

.属性名字

//接上面
val adversary=Jhave()
//set
adversary.hitPoints=1
//get
adversary.hitPoints

java 调用 kotlin

方法1

HeroKt.kt
fun makeProclamation()="Greetings,beast!"

java

HeroKt.makeProclamation()
1.@JvmName

方法2 @file:JvmName()

HeroKt.kt

@file:JvmName("Hero")

fun makeProclamation()="Greetings,beast!"

java

Hero.makeProclamation()
2.@JvmField

方法1

class Spellbook{
	val spells = listOf("AAA","BBB")
}
Spellbook spellbook=new Spellbook ();
spellbook.getSpells();

方法2

class Spellbook{
	@JvmField
	val spells = listOf("AAA","BBB")
}
Spellbook spellbook=new Spellbook ();
spellbook.getSpells();
3.@JvmOverloads

kotlin 提供带有默认参数的函数

//调用者可以指定英雄左手或右手拿什么食物,或者使用默认的配置左手拿苹果,右手拿牛肉
@JvmOverloads
fun handOverFood(leftHand:Stirng="apples",rightHand:String="beef"){
	println("$leftHand $rightHand")
}

java中调用kotlin

Hero.handOverFood("pear")
4.@JvmStatic 伴生对象

@JvmField 注解还能用来以静态的方式提供伴生对象里定义的值
@JvmStatic注解的作用类似于@JvmField ,允许直接调用伴生对象里的函数

class Spellbook{
	compaoion object{
		@JvmField
		val MAX_SPELL_COUNT=10
		@JvmStatic
		fun getSpellGretting()=print("aaaaaa")
	}
}

java调用

Spellbook.MAX_SPELL_COUNT;
Spellbook.getSpellGretting();
5.@Throws
@Throws(IOException::class)
fun acceptApology() {
    throw  IOException()
}

aaaa.extengHandle()
public void extengHandle() throws IOException{
	throw new RuntimeException();
}
try{
	extengHandle();
}catch(IOException e){
	e.printStackTrace();
}

32. kotlin 和 java 函数类型操作 FunctionN N参数个数

jdk 8之前不支持lamble, Function1代表参数有一个 直到Function 22

//变量=匿名函数
//将其改成小写字母,再大写第一个字符,最后打印字符串
val translator = { aa: String ->
    println(aa.toLowerCase().capitalize())
}
 Function1<String, Unit> translator=  PlayerKt.getTranslator();
 translator.invoke("TRUE");

33 .Android 开发使用Kotlin

你可能感兴趣的:(Kotlin,kotlin,android,开发语言)