天天看點

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

文章目錄

  • 函數式程式設計
    • 舉個栗子:forEach
  • 傳統寫法的缺點
  • 高階函數
    • maxBy、minBy
    • filter
    • map
    • any
    • count
    • find
    • groupBy
  • DSL
    • 擴充函數

函數式程式設計

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

舉個栗子:forEach

var print = fun (name:String):Unit{
	println(name)
}

fun main(args: Array<String>) {
	var names = listOf<String>("Tom,Jerry,Lucy")
	//forEach接收的參數為一個函數
	names.forEach(print)
}
           

運作結果

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

forEach接收的參數為一個函數,這個函數叫action,這個函數的作用就是:在集合裡周遊,對于每個element都執行這個函數

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

是以上邊的代碼等價于

for(element in names){
		println(element)
	}
           

forEach就是一個高階函數,高階函數就是參數或傳回值是函數的函數

剛才的寫法是比較麻煩的,簡化如下:

var names = listOf<String>("Tom,Jerry,Lucy")
	names.forEach{
		a -> println(a)
	}
           

forEach後邊跟一個大括号,裡邊是一個匿名函數,參數是a,函數的内容是println(a)

還可以進一步簡化,參數預設是it

var names = listOf<String>("Tom,Jerry,Lucy")
	names.forEach{
		println(it)
	}
           

這樣的一段代碼,就叫閉包

一段程式代碼通常由常量、變量和表達式組成,然後使用一對花括号“{}”來表示閉合,并包裹着這些代碼,由這對花括号包裹着的代碼塊就是一個閉包

傳統寫法的缺點

現在有一個類Girl,裡邊存儲了同宿舍女生的資訊

data class Girl(var name:String,var age:Int,var height:Int,var address:String)
var girls = listOf<Girl>(
	Girl("瓊瓊",27,163,"滄州"),
	Girl("嫚嫚",29,160,"廊坊"),
	Girl("二帆",30,160,"廊坊"),
	Girl("真真",28,168,"福建"),
	Girl("富婆",30,158,"貴州")
)
           

傳送門:【Kotlin】data class

現在篩選出廊坊的舍友,寫一個測試類HelloWorld

fun main(args: Array<String>) {
	var langfangGirl = ArrayList<Girl>()
	for(girl in girls){
		if(girl.address == "廊坊"){
			langfangGirl.add(girl)
		}
	}
	for(girl in langfangGirl){
		println("${girl.address} ${girl.age} 的 ${girl.name}")
	}
}
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

當然可以在Girl.kt中寫一個方法

......
fun filterByAddress(address:String){
	var addressGirls = ArrayList<Girl>()
	for(girl in girls){
		if(girl.address == address){
			addressGirls.add(girl)
		}
	}
	for(girl in addressGirls){
		println("${girl.address} ${girl.age} 的 ${girl.name}")
	}
}
           

測試類中可以直接調用了

fun main(args: Array<String>) {
	filterByAddress("貴州")
}
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

現在要通過年齡篩選,是以再增加一個按年齡篩選的方法,篩選出小于某一年齡的舍友

fun filterByAge(age:Int){
	var ageGirls = ArrayList<Girl>()
	for(girl in girls){
		if(girl.age < age){
			ageGirls.add(girl)
		}
	}
	for(girl in ageGirls){
		println("${girl.address} ${girl.age} 的 ${girl.name}")
	}
}
           

現在又要通過位址和年齡兩個篩選條件篩選,是以再增加一個方法

fun filterByAddressAge(address:String,age:Int){
	var addressAgeGirls = ArrayList<Girl>()
	for(girl in girls){
		if((girl.address == address) and (girl.age < age)){
			addressAgeGirls.add(girl)
		}
	}
	for(girl in addressAgeGirls){
		println("${girl.address} ${girl.age} 的 ${girl.name}")
	}
}
           

通過上邊的需求的不斷變化,可以發現,幾個需求的實作方法基本是複制粘貼,那麼怎樣讓代碼更簡潔呢,需要了解以下知識了

高階函數

maxBy、minBy

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

現在有個需求,找到宿舍中最年長的舍友,如果按照java程式員的思路是這樣寫的

var maxAge = 0
	for(girl in girls){
		if(girl.age > maxAge){
			maxAge = girl.age
		}
	}
	
	println("年齡最大的值是${maxAge}")
	
	for(girl in girls){
		if(girl.age == maxAge){
			println(girl)
		}
	}
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

如果是Kotlin程式員,這個需求對于他們來說就太簡單了

maxBy方法傳回第一個滿足指定評判标準的最大值

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

也可以找到年齡最低的舍友

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

filter

現在篩選年齡<29,身高>165的舍友

println(girls.filter{
		(it.age<29) and (it.height > 160)
	})
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

map

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL
println(girls.map{
		"${it.name}:${it.age}"
	})
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

any

判斷有沒有29歲的舍友

println(girls.any{
		it.age == 29
	})
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

count

查找年齡<29歲的舍友的數量

println(girls.count{
		it.age < 29
	})
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

find

找到第一個符合條件的舍友并傳回,例如查找位址為福建的舍友

println(girls.find{
		it.address == "福建"
	})
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

groupBy

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

按照地區進行分組

println(girls.groupBy{
		it.address
	})
           

檢視運作結果

{滄州=[Girl(name=瓊瓊, age=27, height=163, address=滄州)], 
 廊坊=[Girl(name=嫚嫚, age=29, height=160, address=廊坊), Girl(name=二帆, age=30, height=160, address=廊坊)],
 福建=[Girl(name=真真, age=28, height=168, address=福建)], 
 貴州=[Girl(name=富婆, age=30, height=158, address=貴州)]}
           

查找地區為廊坊的小夥伴,并列印,注意

?

,不為空列印

girls.groupBy{
		it.address
	}.get("廊坊")?.forEach{
		println(it)
	}
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

DSL

【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

擴充函數

在Girls.kt中增加一個方法

fun List<Girl>.findAge(age:Int){
	filter{
		it.age < age
	}.forEach{
		println(it)
	}
}
           

測試下

fun main(args: Array<String>) {
	girls.findAge(28)
}
           
【Kotlin】高階函數函數式程式設計傳統寫法的缺點高階函數DSL

我們可以用關鍵字

infix

修改方法

infix fun List<Girl>.findAge(age:Int){
	filter{
		it.age < age
	}.forEach{
		println(it)
	}
}
           

調用的時候就可以直接空格調用了

運作結果是一樣的