Kotlin学习笔记(四) 集合(下)

集合

十一、取集合的一部分

  • 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()从头获取指定数量的元素,takeLast()从尾开始获取。

drop()从头去除指定数量的元素,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():从集合末尾获取与谓词匹配的元素区间。

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():将集合分解为给定大小的块。参数:块的大小;返回值:一个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():检索给定大小的集合元素中所有可能区间。

可选参数:

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]

构建两个元素的窗口: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()用一个整数作为参数。

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表达式。使用一个越界位置调用时,返回对给定值调用lambda表达式的结果。

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():得到使调用谓词为true的第一个元素。

带有谓词的last():得到使调用谓词为true的最后一个元素。

安全调用: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()

十三、排序

大多数内置类型可比较:

— 数值类型:使用传统的数值顺序。

CharString:使用字典顺序。

如果需要为自定义类型定义一个自然顺序,可以继承Comparable并实现compareTo()函数。

compareTo() 必须将另一个具有相同类型的对象作为参数并返回一个整数值:

— 正值表明接收者对象更大;

— 负值说明参数更大;

— 0 说明对象相等。

如果需要为类型自定义顺序,可以创建一个ComparatorComparator包含compare()函数。

val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
println(listOf("aaa", "bb", "c").sortedWith(lengthComparator))
// [c, bb, aaa]

可以使用compareBy()函数定义一个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()函数返回以随机顺序排序的新List

val numbers = listOf("one", "two", "three", "four")
println(numbers.shuffled())

十四、聚合

  • 常用聚合操作

min()max():最小元素和最大元素。

average():所有元素的平均值。

sum():所有元素的总和。

count():元素的数量。

通过选择器函数或自定义Comparator检索最大和最小元素:

maxBy() / minBy():接受一个选择器函数。

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
  • 高级求和函数

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

依次将所提供的操作应用于集合元素并返回累积的结果。

fold():接受一个初始值并用作第一步的累积值。

reduce():将第一个和第二个元素作为第一步的操作参数。

第一个参数为累积值,第二个参数为元素。

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 }  //第一个元素在结果中没有加倍
println(sumDoubledReduce)  // 37 = 5 + 4 + 20 + 8

foldRight()redeceRight():从右至左将函数应用于元素。第一个参数为元素,第二个参数为累积值。

val numbers = listOf(5, 2, 10, 4)
val sumDoubledRight = numbers.foldRight(0) { element, sum -> sum + element * 2 }
println(sumDoubledRight)  // 42

将元素索引作为参数:foldIndexed()reduceIndexed()

从右至左:foldRightIndexedreduceRightIndexed()

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()函数。

一个参数:要添加的元素。

两个参数:第一参数表示添加的位置,第二参数表示要添加的元素。

添加参数集合的每个元素:使用addAll()函数。

单个参数:要添加的集合。

两个参数:第一参数表示添加的位置,第二参数表示要添加的集合。

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()函数。

val numbers = mutableListOf(1, 2, 3, 4, 3)
numbers.remove(3)  // [1, 2, 4, 3] 删除第一个匹配的元素
println(numbers)
numbers.remove(5)  // 没有删除任何元素
println(numbers)

移除多个元素:

removeAll():移除参数集合中存在的所有元素。可以用谓词调用。

retainAll():移除出参数集合中的元素之外的所有元素。可以用谓词调用。

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(-=)运算符:

右边是单个元素时,-= 会移除它的第一个匹配项。 如果它是一个集合,那么它的所有元素的每次出现都会删除。 第二个操作数可以包含集合中不存在的元素。

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相关操作

  • 按索引取元素

get()函数或简写语法[index]

getOrElse():提供用于计算默认值的函数,如果集合中不存在索引则返回默认值。

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]
  • 查找元素位置
  1. 线性查找

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

接受谓词的函数: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
  1. 二分查找

搜索一排宿列表中的元素,并将该值作为参数传递。如果存在则返回索引;否则返回-insertionPoint - 1,其中insertPoint为应插入此元素的索引。

还可以指定搜索区间:左闭右开。

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,应提供一个Comparator,该列表必须根据此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 { it.price }.thenBy { it.name }))
    // 1
}

使用比较函数无需提供明确的搜索值。它需要使用一个比较函数将元素映射到Int值,并搜索函数返回0的元素。该列表必须根据提供的函数以升序排序。

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
}
  • 写操作
  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]
  1. 更新:

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)
  1. 删除:

removeAt():删除指定位置的元素。

val numbers = mutableListOf(1, 2, 3, 4)
numbers.removeAt(3)
println(numbers)  // [1, 2, 3]
  1. 排序:

asReversed()在可变列表上调用会返回另一个可变列表,该列表是原始列表的反向视图。在该视图中的更改将反映在原始列表中。

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 { 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相关操作

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操作,但是结果仍然是Set,因此删除所有重复的元素。

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相关操作

  • 取键与值

get():采用键作为参数。简写为[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

获取所有键和所有值:keysvalues属性。

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():参数为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:当右操作数中有左操作Map中已存在的键时,使用右侧的值。

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:右操作数可以是单个键或键的集合。

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}
  • 写操作
  1. 添加与更新条目

put():第一参数为键,第二参数为值。简写为[key]语法。

putAll():参数可以是Map或一组PairIterableSequenceArray

如果给定键已存在,则旧值被覆盖。

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}
  1. 删除条目

remove():参数可以是键或整个键值对,如果同时制定键和值,仅当键值都匹配时,才会删除。

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中调用remove()。在.values中调用时, 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}

你可能感兴趣的:(Kotlin学习笔记(四) 集合(下))