Iterable<T>相關函式
Functional Programming
原本的集合不會動到,複製一份給其它函式去執行,傳回新的結果。
Iterable.擴展函式() 
Iterable是集合,List、Set都是Iterable的子類別,就可以用Iterable
以下建立取出第1個元素的泛型擴展函式,並讓list與set使用。
1
2
3
4
5
6
7
8
9
10
fun <T> Iterable<T>.getFirst(): T {
    return this.first()
}
fun main() {
    val list = listOf<String>("Mary", "Alex", "Bill")
    val set1: Set<String> = setOf("Alice", "Mary", "Mary", "Alice")
    println(list.getFirst())
    println(set1.getFirst())
}
Mary
Alice
Iterable是一個Interface,子類別list、set、map會實作iterator(),可以使用Range與for()迴圈,遍歷每個元素。
1
2
3
4
public interface Iterable<out T> {
    // Returns an iterator over the elements of this object.
    public operator fun iterator(): Iterator<T>
}
IntRange
IntRage繼承IntProgression,IntProgression實作Iterator,實作hasNext()、nextInt()函式,遍歷每個元素。
1
2
3
4
5
6
7
8
9
class IntRange(start: Int, end: Int) : IntProgression(start, end, 1) {
    override fun iterator(): IntIterator {
        return object : IntIterator() {
            private var current = first
            override fun hasNext(): Boolean = current <= last
            override fun nextInt(): Int = current++
        }
    }
}
1
2
3
for (i in 2 .. 7) {
    print("$i ")     // 輸出: 2 3 4 5 6 7
}
Iterable.map()擴展函式 
Iterable
擴展函式程式碼如下:
1
2
3
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {
    return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}
集合元素字串長度
以下程式碼會傳回list元素的長度,傳回新的list,不會修改到原本的list。
it代表每個集合元素。
1
2
3
4
5
fun main() {
    val list = listOf<String>("Mary", "Bill", "Alex", "Ben")
    val result = list.map { it.length }
    println(result)
}
[4, 4, 4, 3]
加上前綴字串
以下程式碼為每個元素加上前綴字串,不會修改原本list,會複製一份新的lis,修改複本傳回。
傳回的list的大小跟原本的list的大小一樣。
1
2
3
4
5
6
fun main() {
    val list = listOf<String>("Mary", "Bill", "Alex", "Ben")
        .map { "Little " + it }
        .map { "Happy " + it }
    println(list)
}
[Happy Little Mary, Happy Little Bill, Happy Little Alex, Happy Little Ben]
flatMap
flatMap主要是把二維List變成一維List。
以下是二維List。
1
val list2d = listOf(listOf(1,2,3), listOf(4,5,6))
flatMap擴展函式,傳入一個空的ArrayList到flatMapTo()函式。
1
2
3
public inline fun <T, R> Iterable<T>.flatMap(transform: (T) -> Iterable<R>): List<R> {
    return flatMapTo(ArrayList<R>(), transform)
}
實際真正做事的擴展函式是以下這個。
this是二維List,二維List每個元素都是一維陣列,使用for遍歷二維List,element就是一維陣列。
1
2
3
4
5
6
7
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.flatMapTo(destination: C, transform: (T) -> Iterable<R>): C {
    for (element in this) {
        val list = transform(element)
        destination.addAll(list)
    }
    return destination
}
二維List
1
val list2d = listOf(listOf(1,2,3), listOf(4,5,6))
第1次循環的element是
1
listOf(1,2,3)
第2次循環的element是
1
listOf(4,5,6)
把每一個元素(一維List),加入到新的ArrayList中。
1
destination.addAll(list)
transform Lambda
每個一維List,傳入transform Lambda。
1
val list = transform(element)
transform類型: (T) -> Iterable
以下Lambda{},參數是一維的list,傳回值也是一維的list。
list也是Iterable的子類。
1
2
val list2d = listOf(listOf(1,2,3), listOf(4,5,6))
val list = list2d.flatMap { innerList -> innerList }
因為參數只有一個,可以用it來取代,it就是一維的list,傳回一維的list。
1
2
val list2d = listOf(listOf(1,2,3), listOf(4,5,6))
val list = list2d.flatMap { it }
完整程式碼:把二維List變成一維List
1
2
3
4
5
6
fun main() {
    val list = listOf(
        listOf(1, 2, 3),
        listOf(4, 5, 6)).flatMap { it }
    println(list)
}
[1, 2, 3, 4, 5, 6]
fold 疊加函式
計算List中元素的總合,total的初始值是0。
1
2
3
4
5
val result = listOf(20, 30, 40).fold(0) {
    total, num ->
    total + num
}
println(result)
90
計算List中元素的總合,total的初始值是5。
1
2
3
4
5
val result = listOf(20, 30, 40).fold(5) {
    total, num ->
    total + num
}
println(result)
95
計算List中 「元素*3」 的總合,total的初始值是5。
1
2
3
4
5
val result = listOf(20, 30, 40).fold(5) {
    total, num ->
    total + num * 3
}
println(result)
275
zip 合併
二種不同的集合,把它們合併變成Pair。
以下有名字的List,年齡的List,透過names.zip(ages)合併後,name變成Key,age變成Value,變成一個Pair物件存在List中,再透過toMap()轉成Map。
1
2
3
4
val names = listOf("Mary", "Bill", "Alex")
val ages = listOf(10, 20, 30)
val map = names.zip(ages).toMap()
println(map["Mary"])
10