目录
3.代码简洁之路-局部函数和扩展:在函数中嵌套这些被提取的函数
1.JoinToString
println(strings.joinToString(separator = "; ",prefix = "(",postfix = ")"))
控制台输出:(first; second; fourtg)
fun <T> Collection<T>.joinToString(separator: String = ", ", prefix: String = "", postfix: String = ""): String {
val result = StringBuilder(prefix)
for ((index,element) in this.withIndex()){
if(index>0) result.append(separator)
result.append(element)
}
result.append(postfix)
return result.toString()
}
2.分割字符串
println("list.324-432.A".split("\\.|-".toRegex()))
控制台输出: [list, 324, 432, A]
3.代码简洁之路-局部函数和扩展:在函数中嵌套这些被提取的函数
fun saveUser(user: User){
user.validateBeforeSave()
}
fun User.validateBeforeSave(){
fun validate(value:String,fieldName:String){
if(value.isEmpty()){
throw IllegalArgumentException("Can't ave user $id:empty $fieldName")
}
}
validate(name,"Name")
validate(address,"Address")
}
class User(val id:Int,val name:String,val address:String)
4.列表中找年龄最大
kotlin 库函数 maxBy
val people = listOf(Person("Alcie", 29), Person("Bob", 31))
println(people.maxBy { it.age })
data class Person(val name: String, val age: Int)
//传统方法
val people = listOf(Person("Alcie", 29), Person("Bob", 31))
findTheOldest(people)
data class Person(val name: String, val age: Int)
fun findTheOldest(people: List<Person>) {
var maxAge = 0
var theOldest: Person? = null
for (person in people) {
if (person.age > maxAge) {
maxAge = person.age
theOldest = person
}
}
println(theOldest)
}
5.lambda
people.maxBy({ p: Person -> p.age})
kotlin语法约定:如何lambda表达式是函数调用的最后一个实参,那它可以放到括号的外面
people.maxBy(){ p: Person -> p.age}
当lambda是函数唯一实参时,可以去掉空括号对
people.maxBy{ p: Person -> p.age} //显式地写出参数类型
省略lambda参数类型
people.maxBy{ p-> p.age} //推导出参数类型
如果上下文期望的是只有一个参数的lambda且这个参数的类型可以推断出来,则it代替命名参数
people.maxBy{ it.age} //“it”是自动生成的参数名称
成员引用
people.maxBy(Person :: age)
6.函数集合API
基础 filter map :filter函数可以从集合中移除你不想要的元素,但是它并不会改变这些元素,元素变换是map的用武之地
data class Person(val name: String, val age: Int)
val people = listOf(Person("Alcie", 29), Person("Bob", 31))
println(people.filter { it.age>30 })
控制台输出 [Person(name=Bob, age=31)]
val list= listOf(1,2,3,4)
println(list.map{it * it})
控制台输出 [1, 4, 9, 16]
flatmap toSet
fun main(args: Array<String>) {
val books= listOf(Book("朝花夕拾", listOf("鲁迅")),
Book("呐喊", listOf("鲁迅")),
Book("史记", listOf("司马迁")))
println(books.flatMap { it.authors })
println(books.flatMap { it.authors }.toSet())
}
class Book(val title:String,val authors:List<String>)
控制台输出:
[鲁迅, 鲁迅, 司马迁]
[鲁迅, 司马迁]
with apply
println(alphabet())
控制台输出:
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Now IKnow the alohabet!
fun alphabet():String{
val result=StringBuilder()
for (letter in 'A'..'Z'){
result.append(letter)
}
result.append("\nNow IKnow the alohabet!")
return result.toString()
}
fun alphabet1():String{
val result=StringBuilder()
return with(result){
for (letter in 'A'..'Z'){
result.append(letter)
}
append("\nNow IKnow the alohabet!")
this.toString()
}
}
fun alphabet2()= with(StringBuilder()){
for (letter in 'A'..'Z'){
append(letter)
}
append("\nNow IKnow the alohabet!")
this.toString()
}
fun alphabet3()= StringBuilder().apply{
for (letter in 'A'..'Z'){
append(letter)
}
append("\nNow IKnow the alohabet!")
}.toString()
7.高阶函数:Lambda 作为形参和返回值
高阶函数就是以另一个函数作为参数或返回值的函数。
println("ab5c".filter { it in 'a'..'z' })
fun String.filter(predicate:(Char)->Boolean):String{
val sb=StringBuilder()
for (index in 0 until length){
val element=get(index)
if (predicate(element)) sb.append(element)
}
return sb.toString()
}
控制台输出:abc
8. 函数类型参数,并用一个lambda作为默认值
println(letters.jointToString { it.toLowerCase() })
控制台输出:aplha, beta
println(letters.jointToString(separator="! ",postfix="! ",transform={ it.toUpperCase() }) )
控制台输出:APLHA! BETA!
fun <T> Collection<T>.jointToString(
separator: String = ", ",
prefix: String = "",
postfix: String = "",
transform: (T) -> String = { it.toString() }
): String {
val result = StringBuilder(prefix)
for ((index, element) in this.withIndex()) {
if (index > 0) result.append(separator)
result.append(transform(element))
}
result.append(postfix)
return result.toString()
}
参数可空的函数类型 invoke
println(letters.jointToString { it.toLowerCase() })
控制台输出:aplha, beta
println(letters.jointToString(separator="! ",postfix="! ",transform={ it.toUpperCase() }) )
控制台输出:APLHA! BETA!
fun <T> Collection<T>.jointToString(
separator: String = ", ",
prefix: String = "",
postfix: String = "",
transform: (T) -> String = { it.toString() }
): String {
val result = StringBuilder(prefix)
for ((index, element) in this.withIndex()) {
if (index > 0) result.append(separator)
val str=transform.invoke(element)?:element.toString()
result.append(str)
}
result.append(postfix)
return result.toString()
}
9.通过lambda去除重复代码
data class SiteVisit(val path: String, val duration: Double, val os: OS)
enum class OS { WINDOWS, LINUX, MAC, IOS, ANDROID }
val log = listOf(
SiteVisit("/", 34.0, OS.WINDOWS),
SiteVisit("/", 22.0, OS.MAC),
SiteVisit("/login", 12.0, OS.WINDOWS),
SiteVisit("/signup", 8.0, OS.IOS),
SiteVisit("/", 16.3, OS.ANDROID)
)
val averageWindowsDuration = log
.filter { it.os == OS.WINDOWS }
.map(SiteVisit::duration)
.average()
println(averageWindowsDuration)
控制台输出 :23.0
将重复代码抽取到 普通函数
fun List<SiteVisit>.averageDurationFor(os: OS) =
filter { it.os == os }.map(SiteVisit::duration).average()
println(log.averageDurationFor(OS.WINDOWS))
控制台输出 :23.0
变复杂
val averageWindowsDuration1 = log
.filter { it.os in setOf(OS.IOS, OS.ANDROID) }
.map(SiteVisit::duration)
.average()
println(averageWindowsDuration1)
控制台输出 : 12.15
高阶函数去除重复代码
fun List<SiteVisit>.averageDurationFor1(predicate: (SiteVisit) -> Boolean) =
filter(predicate).map(SiteVisit::duration).average()
println(log.averageDurationFor1 { it.os in setOf(OS.IOS, OS.ANDROID) })
控制台输出 : 12.15