集合相关:
概述
自从Java 8支持了lambda表达式以来,Lambda表达式是实现大量函数特性的基础,让Java开发越来越趋向于流程式开发。在Kolin中,对Lambda表达式有完美的支持,又因为扩展这一特性,Kotlin也走在了函数式编程的前沿。对于集合,Kotlin提供的不同类型集合,在标准库中,对这些集合实现了一些扩展,以更种方式对集合操作。熟练的函数式编程的基础,是对相关函数有一定的认识和了解。话不多说,先看集合的这些操作到底有哪些?具体实现的功能?
集合接口
- Iterable:父类。任何类继承这个接口就表示可以遍历序列的元素。
- MutableIterable:在迭代期间支持移除项目的迭代。
- Collection:这个类表示元素的泛型集合。我们可以访问函数:返回集合尺寸、集合是否为空、包含一项或一组。由于集合是不可变的,这类集合的所有方法只能请求数据。
- MutableCollection:支持添加和移除元素的Collection。它提供额外的函数,如:add、remove或clear等等。
- List:或许这是最常用的集合。这表示有序的元素泛型集合。由于是有序的,我们可以用get函数,按照项目的位置请求项目。
- MutableList:支持添加和移除元素的List。
- Set:不支持重复元素的无序元素集合。
- MutableSet:支持添加和移除元素的Set。
- Map:key-value(键-值)对集合。在映射表(map)中key(键)是唯一的,就是说在一个映射表中不能有两对有相同的key。
- MutableMap:支持添加和移除元素的Map。
List/Set操作
val bookA = Book("A", 20, "Jone")
val bookB = Book("B", 21, "Green")
val bookC = Book("C", 22, "Mark")
val bookD = Book("D", 23, "Node")
val bookE = Book("E", 24, "Blue")
val listBook = listOf<Book>(bookA, bookB, bookC, bookD, bookE)
聚合操作
所谓的聚合操作就是从值集合计算得出单个值
any
如果集合中至少有一个元素与指定条件相符,则返回true;否则,返回false.在any的函数体内,指定判断元素的条件。
函数参数类型
- predicate: (T) -> Boolean
返回值:
- Boolean
示例代码:
val any_22: Boolean = listBook.any { it.page > 22 }
val any_33: Boolean = listBook.any { it.page > 33 }
println("any_22: $any_22, any_33: $any_33") // Log: any_22: true, any_33: false
all
如果集合中所有元素与指定条件相符,则返回true;否则,返回false.在all的函数体内,指定判断元素的条件。
函数参数类型
- predicate: (T) -> Boolean
返回值:
- Boolean
示例代码:
val all_20: Boolean = listBook.all { it.page >= 20 }
val all_22: Boolean = listBook.all { it.page > 22 }
println("all_20: $all_20, all_22: $all_22") // Log: all_22: true, all_33: false
count
返回集合与指定条件相符的元素个数。在count的函数体内,指定判断元素的条件。若不指定条件,返回集合中所有元素的个数。
函数参数类型
- predicate: (T) -> Boolean
返回值:
- Int
示例代码:
val count: Int = listBook.count {it.page > 23}
println("count: $count")
fold
将对集合从第一个到最后一个元素的操作结果进行累加,并加上初始值。
函数参数类型
- R: 初始值
- operation: (T, R) -> R
返回值:
- R
示例代码:
val fold = listBook.fold(0, ::ops)
println("fold: $fold") // Log: fold: 110
fun ops(total: Int, book: Book): Int {
var t = total
t += book.page
println("total: $t, book: $book")
return t
}
// Log
total: 20, book: Book(name='A', page=20, author='Jone')
total: 41, book: Book(name='B', page=21, author='Green')
total: 63, book: Book(name='C', page=22, author='Mark')
total: 86, book: Book(name='D', page=23, author='Node')
total: 110, book: Book(name='E', page=24, author='Blue')
fold: 110
foldRight
与fold类似,不同的是从最后一个元素到第一个元素。另外,传递的函数的参数类型也不一样,哪里不同,可以对比下ops和opsRight两个函数的参数类型。
函数参数类型
- R: 初始值
- operation: (T, R) -> R
返回值:
- R
示例代码:
val foldRight = listBook.foldRight(0, ::opsRight)
println("foldRight: $foldRight")
fun opsRight(book: Book,total: Int): Int {
var t = total
t += book.page
println("total: $t, book: $book")
return t
}
// Log
total: 24, book: Book(name='E', page=24, author='Blue')
total: 47, book: Book(name='D', page=23, author='Node')
total: 69, book: Book(name='C', page=22, author='Mark')
total: 90, book: Book(name='B', page=21, author='Green')
total: 110, book: Book(name='A', page=20, author='Jone')
foldRight: 110
forEach
对每个元素执行指定的操作,实际效果就是对集合的遍历。
listBook.forEach (::println)
// Log
book: Book(name='A', page=20, author='Jone')
book: Book(name='B', page=21, author='Green')
book: Book(name='C', page=22, author='Mark')
book: Book(name='D', page=23, author='Node')
forEachIndexed
与forEach类似,不同的是在遍历元素的同时获得元素的索引。
listBook.forEachIndexed{index, book ->
run {
println("index: $index, book: $book")
}
}
// Log
index: 0, book: Book(name='A', page=20, author='Jone')
index: 1, book: Book(name='B', page=21, author='Green')
index: 2, book: Book(name='C', page=22, author='Mark')