集合
十一、取集合的一部分
-
Slice
slice()
返回具有給定索引的集合元素列表。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.slice(1..3)) // [two, three, four]
println(numbers.slice(0..4 step 2)) // [one, three, five]
println(numbers.slice(listOf(3, 5, 0))) // [four, six, one]
-
Take 與 Drop
take()
從頭獲取指定數(shù)量的元素,takeLast()
從尾開始獲取。
drop()
從頭去除指定數(shù)量的元素,dropLast()
從尾開始去除。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.take(3)) // [one, two, three]
println(numbers.takeLast(3)) // [four, five, six]
println(numbers.drop(4)) // [five, six]
println(numbers.dropLast(5)) // [one]
takeWhile()
:不停獲取元素直到排除與謂詞匹配的首個元素。
takeLastWhile()
:從集合末尾獲取與謂詞匹配的元素區(qū)間。
dropWhile()
:返回從首個與謂詞不匹配的元素到末尾元素。
dropLastWhile()
:返回從開頭到最后一個與謂詞不匹配的元素。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.takeWhile { !it.startsWith('f') })
// [one, two, three]
println(numbers.takeLastWhile { it != "three" })
// [four, five, six]
println(numbers.dropWhile { it.length == 3 })
// [three, four, five, six]
println(numbers.dropLastWhile { it.contains('i') })
// [one, two, three, four]
-
Chunked
chunked()
:將集合分解為給定大小的塊。參數(shù):塊的大小;返回值:一個List
其中包含給定大小的List
。
val numbers = (0..13).toList()
println(numbers.chunked(3))
// [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13]]
println(numbers.chunked(3) { it.sum() })
// [3, 12, 21, 30, 25]
-
Windowed
windowed()
:檢索給定大小的集合元素中所有可能區(qū)間。
可選參數(shù):
— step
兩個相鄰窗口的第一個元素之間的距離,默認為1。
— partialWindows
是否包含小于給定大小的窗口,默認為false。
val numbers = (1..10).toList()
println(numbers.windowed(3, step = 2, partialWindows = true))
// [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]]
println(numbers.windowed(3, step = 2))
// [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9]]
println(numbers.windowed(3, step = 2) { it.sum() })
// [6, 12, 18, 24]
構(gòu)建兩個元素的窗口:zipWithNext()
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.zipWithNext())
// [(one, two), (two, three), (three, four), (four, five)]
println(numbers.zipWithNext { s1, s2 -> s1.length > s2.length})
// [false, false, true, false]
十二、取單個元素
-
按位置取
elementAt()
用一個整數(shù)作為參數(shù)。
val numbers = linkedSetOf("one", "two", "three", "four", "five")
println(numbers.elementAt(3)) // four
val numbersSortedSet = sortedSetOf("one", "two", "three", "four")
println(numbersSortedSet.elementAt(0)) // four
List
可以使用get()
和[]
。
檢索第一個和最后一個元素:first()
和last()
。
避免越界,使用elementAt()
的安全變體:
— elementAtOrNull()
:指定位置超出集合范圍時,返回null
。
— elementAtOrElse()
:接受一個lambda表達式。使用一個越界位置調(diào)用時,返回對給定值調(diào)用lambda表達式的結(jié)果。
val numbers = listOf("one", "two", "three", "four", "five")
println(numbers.elementAtOrNull(5)) // null
println(numbers.elementAtOrElse(5) { i -> "numbers[$i] is undefined"}) // numbers[5] is undefined
-
按條件取
帶有謂詞的first()
:得到使調(diào)用謂詞為true
的第一個元素。
帶有謂詞的last()
:得到使調(diào)用謂詞為true
的最后一個元素。
安全調(diào)用:firstOrNull()
和lastOrNull()
。
find()
可以代替firstOrNull()
,findLast()
可以代替lastOrNull()
。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.first { it.length > 3 }) // three
println(numbers.last { it.startsWith("f") }) // five
println(numbers.firstOrNull { it.length > 5 }) // null
println(numbers.lastOrNull { it.length < 4 }) // six
println(numbers.find { it.length > 5 }) // null
println(numbers.findLast { it.length < 4 }) // six
-
隨機取
val numbers = listOf(1, 2, 3, 4)
println(numbers.random())
-
檢測存在與否
檢測某個元素:contains()
和in
。
檢測多個元素:containsAll()
。
val numbers = listOf("one", "two", "three", "four", "five", "six")
println(numbers.contains("four")) // true
println("zero" in numbers) // false
println(numbers.containsAll(listOf("four", "two"))) // true
println(numbers.containsAll(listOf("one", "zero"))) // false
檢查集合是否為空或非空:isEmpty()
和isNotEmpty()
。
十三、排序
大多數(shù)內(nèi)置類型可比較:
— 數(shù)值類型:使用傳統(tǒng)的數(shù)值順序。
— Char
和String
:使用字典順序。
如果需要為自定義類型定義一個自然順序,可以繼承Comparable
并實現(xiàn)compareTo()
函數(shù)。
compareTo()
必須將另一個具有相同類型的對象作為參數(shù)并返回一個整數(shù)值:
— 正值表明接收者對象更大;
— 負值說明參數(shù)更大;
— 0 說明對象相等。
如果需要為類型自定義順序,可以創(chuàng)建一個Comparator
,Comparator
包含compare()
函數(shù)。
val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
println(listOf("aaa", "bb", "c").sortedWith(lengthComparator))
// [c, bb, aaa]
可以使用compareBy()
函數(shù)定義一個Comparator
,它接受一個lambda表達式。
println(listOf("aaa", "bb", "c").sortedWith(compareBy { it.length }))
// [c, bb, aaa]
-
自然順序
sorted()
:升序。
sortedDescending()
:降序。
val numbers = listOf("one", "two", "three", "four")
println(numbers.sorted()) // [four, one, three, two]
println(numbers.sortedDescending()) // [two, three, one, four]
-
自定義順序
sortedBy()
:升序。
sortedByDescending()
:降序。
val numbers = listOf("one", "two", "three", "four")
println(numbers.sortedBy { it.length }) // [one, two, four, three]
println(numbers.sortedByDescending { it.last() }) // [four, two, one, three]
-
倒序
reversed()
返回帶有元素副本的新集合。
val numbers = listOf("one", "two", "three", "four")
println(numbers.reversed()) // [four, three, two, one]
println(numbers) // [one, two, three, four]
asReversed()
返回相同集合實例的一個反向視圖。
如果原始列表是可變的,所有對原始列表的更改都會反映在反向視圖中,同樣對于反向視圖的更改也會反映在原始列表中。
val numbers = mutableListOf("two", "three")
val reversedNumbers = numbers.asReversed()
println(numbers) // [two, three]
println(reversedNumbers) // [three, two]
numbers.add("four")
println(numbers) // [two, three, four]
println(reversedNumbers) // [four, three, two]
reversedNumbers.add("one")
println(numbers) // [one, two, three, four]
println(reversedNumbers) // [four, three, two, one]
-
隨機順序
shuffled()
函數(shù)返回以隨機順序排序的新List
。
val numbers = listOf("one", "two", "three", "four")
println(numbers.shuffled())
十四、聚合
-
常用聚合操作
— min()
和 max()
:最小元素和最大元素。
— average()
:所有元素的平均值。
— sum()
:所有元素的總和。
— count()
:元素的數(shù)量。
通過選擇器函數(shù)或自定義Comparator
檢索最大和最小元素:
— maxBy()
/ minBy()
:接受一個選擇器函數(shù)。
— maxWith()
/ minWith()
:接受一個Comparator
對象。
val numbers = listOf(5, 42, 10, 4)
val min3Remainder = numbers.minBy { it % 3 }
println(min3Remainder) // 42
val strings = listOf("one", "two", "three", "four")
val longestString = strings.maxWith(compareBy { it.length })
println(longestString) // three
-
高級求和函數(shù)
— sumBy()
— sumByDouble()
val numbers = listOf(5, 42, 10, 4)
println(numbers.sumBy { it * 2 }) // 122
println(numbers.sumByDouble { it.toDouble() / 2 }) // 30.5
-
Fold 與 reduce
依次將所提供的操作應(yīng)用于集合元素并返回累積的結(jié)果。
fold()
:接受一個初始值并用作第一步的累積值。
reduce()
:將第一個和第二個元素作為第一步的操作參數(shù)。
第一個參數(shù)為累積值,第二個參數(shù)為元素。
val numbers = listOf(5, 2, 10, 4)
val sum = numbers.reduce { sum, element -> sum + element }
println(sum) // 21
val sumDoubled = numbers.fold(0) { sum, element -> sum + element * 2 }
println(sumDoubled) // 42
val sumDoubledReduce = numbers.reduce { sum, element -> sum + element * 2 } //第一個元素在結(jié)果中沒有加倍
println(sumDoubledReduce) // 37 = 5 + 4 + 20 + 8
foldRight()
與redeceRight()
:從右至左將函數(shù)應(yīng)用于元素。第一個參數(shù)為元素,第二個參數(shù)為累積值。
val numbers = listOf(5, 2, 10, 4)
val sumDoubledRight = numbers.foldRight(0) { element, sum -> sum + element * 2 }
println(sumDoubledRight) // 42
將元素索引作為參數(shù):foldIndexed()
和reduceIndexed()
。
從右至左:foldRightIndexed
和reduceRightIndexed()
。
val numbers = listOf(5, 2, 10, 4)
val sumEven = numbers.foldIndexed(0) { idx, sum, element -> if (idx % 2 == 0) sum + element else sum }
println(sumEven) // 15 = 5 + 10
val sumEvenRight = numbers.foldRightIndexed(0) { idx, element, sum -> if (idx % 2 == 0) sum + element else sum }
println(sumEvenRight) // 15 = 10 + 5
十五、集合寫操作
-
添加元素
添加單個元素:使用add()
函數(shù)。
一個參數(shù):要添加的元素。
兩個參數(shù):第一參數(shù)表示添加的位置,第二參數(shù)表示要添加的元素。
添加參數(shù)集合的每個元素:使用addAll()
函數(shù)。
單個參數(shù):要添加的集合。
兩個參數(shù):第一參數(shù)表示添加的位置,第二參數(shù)表示要添加的集合。
val numbers = mutableListOf(2, 5)
numbers.add(6)
numbers.add(0, 1)
println(numbers) // [1, 2, 5, 6]
numbers.addAll(arrayOf(7, 8))
numbers.addAll(2, setOf(3, 4))
println(numbers) // [1, 2, 3, 4, 5, 6, 7, 8]
plusAssign(+=)
運算符:
val numbers = mutableListOf("one", "two")
numbers += "three"
println(numbers) // [one, two, three]
numbers += listOf("four", "five")
println(numbers) // [one, two, three, four, five]
-
刪除元素
移除一個元素:remove()
函數(shù)。
val numbers = mutableListOf(1, 2, 3, 4, 3)
numbers.remove(3) // [1, 2, 4, 3] 刪除第一個匹配的元素
println(numbers)
numbers.remove(5) // 沒有刪除任何元素
println(numbers)
移除多個元素:
removeAll()
:移除參數(shù)集合中存在的所有元素。可以用謂詞調(diào)用。
retainAll()
:移除出參數(shù)集合中的元素之外的所有元素。可以用謂詞調(diào)用。
clear()
:移除所有元素并將集合置空。
val numbers = mutableListOf(1, 2, 3, 4)
numbers.retainAll { it >= 3 }
println(numbers) // [3, 4]
numbers.clear()
println(numbers) // []
val numbersSet = mutableSetOf("one", "two", "three", "four")
numbersSet.removeAll(setOf("one", "two", "five"))
println(numbersSet) // [three, four]
minusAssign(-=)
運算符:
右邊是單個元素時,-=
會移除它的第一個匹配項。 如果它是一個集合,那么它的所有元素的每次出現(xiàn)都會刪除。 第二個操作數(shù)可以包含集合中不存在的元素。
val numbers = mutableListOf("one", "two", "three", "four", "three", "five", "five")
numbers -= "three"
println(numbers) // [one, two, four, three, five, five]
numbers -= listOf("four", "five", "six")
println(numbers) // [one, two, three]
十六、List相關(guān)操作
-
按索引取元素
get()
函數(shù)或簡寫語法[index]
。
getOrElse()
:提供用于計算默認值的函數(shù),如果集合中不存在索引則返回默認值。
getOrNull()
:返回null
作為默認值。
val numbers = listOf(1, 2, 3, 4)
println(numbers.get(0)) // 1
println(numbers[0]) // 1
// println(numbers.get(5)) // Exception
println(numbers.getOrNull(5)) // null
println(numbers.getOrElse(5) { it }) // 5
-
取列表的一部分
subList()
:左閉右開。
val numbers = (0..10).toList()
println(numbers.subList(3, 6)) // [3, 4, 5]
-
查找元素位置
- 線性查找
indexOf()
和lastIndexOf()
val numbers = listOf(1, 2, 3, 4, 2, 5)
println(numbers.indexOf(2)) // 1
println(numbers.indexOf(6)) // -1
println(numbers.lastIndexOf(2)) // 4
println(numbers.lastIndexOf(6)) //-1
接受謂詞的函數(shù):indexOfFirst()
和indexOfLast()
val numbers = listOf(1, 2, 3, 4)
println(numbers.indexOfFirst { it > 2 }) // 2
println(numbers.indexOfFirst { it == 5 }) // -1
println(numbers.indexOfLast { it % 2 == 1 }) // 2
println(numbers.indexOfLast { it > 5}) // -1
- 二分查找
搜索一排宿列表中的元素,并將該值作為參數(shù)傳遞。如果存在則返回索引;否則返回-insertionPoint - 1
,其中insertPoint
為應(yīng)插入此元素的索引。
還可以指定搜索區(qū)間:左閉右開。
val numbers = listOf(0, 2, 3, 4)
println(numbers.binarySearch(2)) // 1
println(numbers.binarySearch(1)) // -2
println(numbers.binarySearch(2, 0, 2)) // 1
println(numbers.binarySearch(1, 0, 2)) // -3
如果列表不是COmparable
,應(yīng)提供一個Comparator
,該列表必須根據(jù)此Comparator
以升序排序。
data class Product(val name: String, val price: Double)
fun main() {
val productList = listOf(
Product("WebStorm", 49.0),
Product("AppCode", 99.0),
Product("DotTrace", 129.0),
Product("ReSharper", 149.0))
println(productList.binarySearch(Product("AppCode", 99.0),
compareBy<Product> { it.price }.thenBy { it.name }))
// 1
}
使用比較函數(shù)無需提供明確的搜索值。它需要使用一個比較函數(shù)將元素映射到Int
值,并搜索函數(shù)返回0的元素。該列表必須根據(jù)提供的函數(shù)以升序排序。
import kotlin.math.sign
data class Product(val name: String, val price: Double)
fun priceComparison(product: Product, price: Double) = sign(product.price - price).toInt()
fun main() {
val productList = listOf(
Product("WebStorm", 49.0),
Product("AppCode", 99.0),
Product("DotTrace", 129.0),
Product("ReSharper", 149.0))
println(productList.binarySearch { priceComparison(it, 99.0) })
// 1
}
-
寫操作
- 添加:
val numbers = mutableListOf("one")
numbers.add("four")
println(numbers) // [one, four]
numbers.addAll(listOf("five", "seven" ))
println(numbers) // [one, four, five, seven]
numbers.add(3, "six")
println(numbers) // [one, four, five, six, seven]
numbers.addAll(1, listOf("two", "three"))
println(numbers) // [one, two, three, four, five, six, seven]
- 更新:
set()
和[index]
:在指定位置替換元素。
val numbers = mutableListOf("one", "five", "four")
numbers[1] = "two"
numbers.set(2, "three")
println(numbers)
fill()
:將所有集合元素替換為指定值。
val numbers = mutableListOf(1, 2, 3, 4)
numbers.fill(5)
println(numbers)
- 刪除:
removeAt()
:刪除指定位置的元素。
val numbers = mutableListOf(1, 2, 3, 4)
numbers.removeAt(3)
println(numbers) // [1, 2, 3]
- 排序:
asReversed()
在可變列表上調(diào)用會返回另一個可變列表,該列表是原始列表的反向視圖。在該視圖中的更改將反映在原始列表中。
val numbers = mutableListOf("one", "two", "three", "four")
numbers.sort()
println("Sort into ascending: $numbers")
// [four, one, three, two]
numbers.sortDescending()
println("Sort into descending: $numbers")
// [two, three, one, four]
numbers.sortBy { it.length }
println("Sort into ascending by length: $numbers")
// [two, one, four, three]
numbers.sortByDescending { it.last() }
println("Sort into descending by the last letter: $numbers")
// [four, two, one, three]
numbers.sortWith(compareBy<String> { it.length }.thenBy { it })
println("Sort by Comparator: $numbers")
// [one, two, four, three]
numbers.shuffle()
println("Shuffle: $numbers")
// [one, four, two, three] (隨機)
numbers.reverse()
println("Reverse: $numbers")
// [three, two, four, one]
val reversedNumbers = numbers.asReversed()
println("ReversedNumbers: $reversedNumbers")
// [one, four, two, three]
reversedNumbers.add("five")
println("ReversedNumbers: $reversedNumbers")
// [one, four, two, three, five]
println("numbers: $numbers")
// [five, three, two, four, one]
十七、Set相關(guān)操作
union()
:并集
intersect()
:交集
subtract()
:差集
val numbers = setOf("one", "two", "three")
println(numbers union setOf("four", "five")) // [one, two, three, four, five]
println(setOf("four", "five") union numbers) // [four, five, one, two, three]
println(numbers intersect setOf("two", "one")) // [one, two]
println(setOf("two", "one") intersect numbers) // [two, one]
println(numbers subtract setOf("three", "four")) // [one, two]
println(numbers subtract setOf("three")) // [one, two]
List
也支持Set
操作,但是結(jié)果仍然是Set
,因此刪除所有重復(fù)的元素。
val numbers = listOf("one", "two", "three", "three")
println(numbers union setOf("four", "five")) // [one, two, three, four, five]
println(setOf("four", "five") union numbers) // [four, five, one, two, three]
println(numbers intersect setOf("two", "one")) // [one, two]
println(setOf("two", "one") intersect numbers) // [two, one]
println(numbers subtract setOf("three", "four")) // [one, two]
println(numbers subtract setOf("three")) // [one, two]
十八、Map相關(guān)操作
-
取鍵與值
get()
:采用鍵作為參數(shù)。簡寫為[key]
語法。找不到指定的鍵返回null
。
getValue()
:找不到指定的鍵則拋出異常。
getOrElse()
:找不到指定的鍵返回lambda表達式的值。
getOrDefault()
:找不到指定的鍵返回指定的默認值。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap.get("one")) // 1
println(numbersMap["one"]) // 1
println(numbersMap.getOrElse("four", defaultValue = { 4 })) // 4
println(numbersMap.getOrDefault("four", 4)) // 4
println(numbersMap.get("four")) // null
println(numbersMap["four"]) // null
println(numbersMap.getValue("four")) // Exception
獲取所有鍵和所有值:keys
和values
屬性。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap.keys) // [one, two, three]
println(numbersMap.values) // [1, 2, 3]
-
過濾
filter()
:參數(shù)為Pair()
對象。
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key11" to 11)
val filteredMap = numbersMap.filter { (key, value) -> key.endsWith("1") && value > 10}
println(filteredMap) // {key11=11}
filterKeys()
:按鍵過濾。
filterValues()
:按值過濾。
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key11" to 11)
val filteredKeysMap = numbersMap.filterKeys { it.endsWith("1") }
val filteredValuesMap = numbersMap.filterValues { it < 10 }
println(filteredKeysMap) // {key1=1, key11=11}
println(filteredValuesMap) // {key1=1, key2=2}
-
加減操作
plus
:當(dāng)右操作數(shù)中有左操作Map
中已存在的鍵時,使用右側(cè)的值。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap + Pair("four", 4))
println(numbersMap + Pair("one", 10))
println(numbersMap + mapOf("five" to 5, "one" to 11))
minus
:右操作數(shù)可以是單個鍵或鍵的集合。
val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
println(numbersMap - "one") // {two=2, three=3}
println(numbersMap - listOf("two", "four")) // {one=1, three=3}
-
寫操作
- 添加與更新條目
put()
:第一參數(shù)為鍵,第二參數(shù)為值。簡寫為[key]
語法。
putAll()
:參數(shù)可以是Map
或一組Pair
:Iterable
、Sequence
、Array
。
如果給定鍵已存在,則舊值被覆蓋。
val numbersMap = mutableMapOf("one" to 1)
numbersMap.put("two", 22)
numbersMap["three"] = 33
numbersMap.putAll(setOf("four" to 44, "five" to 55))
println(numbersMap) // {one=1, two=22, three=33, four=44, five=55}
numbersMap.put("two", 2)
numbersMap["three"] = 3
numbersMap.putAll(setOf("four" to 4, "five" to 5))
println(numbersMap) // {one=1, two=2, three=3, four=4, five=5}
+=
操作符:
val numbersMap = mutableMapOf("one" to 1, "two" to 2)
numbersMap += mapOf("three" to 3, "four" to 4)
println(numbersMap) // {one=1, two=2, three=3, four=4}
- 刪除條目
remove()
:參數(shù)可以是鍵或整個鍵值對,如果同時制定鍵和值,僅當(dāng)鍵值都匹配時,才會刪除。
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3)
numbersMap.remove("one")
numbersMap.remove("two", 2)
numbersMap.remove("three", 4)
println(numbersMap)
通過鍵或值刪除條目:在Map
的.keys
或.value
中調(diào)用remove()
。在.values
中調(diào)用時, remove()
僅刪除給定值匹配到的的第一個條目。
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3, "threeAgain" to 3)
numbersMap.keys.remove("one")
println(numbersMap) // {two=2, three=3, threeAgain=3}
numbersMap.values.remove(3)
println(numbersMap) // {two=2, threeAgain=3}
-=
操作符:
val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3)
numbersMap -= "two"
numbersMap -= "five"
println(numbersMap) // {one=1, three=3}