Mrli
别装作很努力,
因为结局不会陪你演戏。
Contacts:
QQ博客园

Kotlin集合、流式操作

2022/01/03
Word count: 3,198 | Reading time: 15min

除了最通用的Array以外,kotlin中还有一类容器统称为Colletion(集合),他们有

  • List
    • List:继承Collection。一个范性有序的只读集合。因为有序,所以,我们可以使用get(position)等查询的方法
    • MutableList:继承List,MutableCollection。一个有序集合。并额外提供了add/remove元素的方法
  • Set
    • Set:继承Collection。一个无序并不支持重复元素的集合
    • MutableSet:继承Set,MutableCollection,一个无序的集合并且不支持重复元素。但是,支持add/remove元素
  • Map
    • Map:一个key-value的只读集合。并且key唯一。
    • MutableMap:继承Map。支持put/remove元素

List

  • any:如果至少有一个元素与判断条件相符,则 返回true

  • all:如果全部元素与判断条件相符,则 返回true

  • component1,…,component5:返回集合的第n个元素,越界返回ArrayIndexOutOfBoundsException

  • contain:如果指定元素可以在集合找到,则 返回true

  • containsAll:如果指定集合所有元素都可以在目标集合找到,则 返回true

  • count:返回与判断条件相符的元素个数

  • distinct:返回一个只包含不同元素的数组,即对列表内元素去重

  • distinctBy:返回集合元素执行指定条件后,不同元素的数组(原始数组元素)

    1
    2
    val list = listOf(1, 4, 2, 2)
    assertEquals(listOf(1,4),list.distinctBy { it%2 == 0})
  • drop:返回所有元素的列表,但不包含前n个元素

    1
    2
    val list = listOf(1,2,3,4)
    assertEquals(listOf(3,4),list.drop(2))
  • dropLast:返回所有元素的列表,但不包含最后n个元素

    1
    2
    val list = listOf(1,2,3,4)
    assertEquals(listOf(1,2),list.dropLast(2))
  • dropWhile:返回所有元素的列表,但不包含满足判断条件的元素

    1
    2
    3
    4
    val list = listOf(4,1,2,3,4)
    assertEquals(listOf(4,1,2,3,4),list.dropWhile{it <3})
    val list = listOf(1,2,3,4)
    assertEquals(listOf(3,4),list.dropWhile{it <3})
  • elementAt:返回指定索引的元素,如果索引越界,则抛出ArrayIndexOutOfBoundsException

    1
    2
    3
    4
    5
    6
    7
    8
    val list = listOf(1,2,3,4)
    assertEquals(4,list.elementAt(3))
    // elementAtOrElse:返回指定索引的元素,如果索引越界,则返回指定的默认值
    val list = listOf(1,2,3,4)
    assertEquals(18,list.elementAtOrElse(6,{it *3}))
    // elementAtOrNull: 返回指定索引的元素,如果索引越界,则返回null
    val list = listOf(1,2,3,4)
    assertEquals(null,list.elementAtOrNull(6))
  • filter:筛选出所有符合条件的元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    val list = listOf(1,2,3,4)
    assertEquals(listOf(2,3),list.filter{ it in 2..3 })
    filterIndexed
    // filterIndexed筛选出所有符合条件的元素(条件多了一个索引参数)
    val list = listOf(1, 4, 2, 2)
    assertEquals(listOf(4),list.filterIndexed { index, it -> index>0 && it >2} )
    // filterNot: 筛选出所有不符合条件的元素
    val list = listOf(1,2,3,4)
    assertEquals(listOf(1,4),list.filterNot{ it in 2..3 })
    filterNotNull
    // filterNotNull: 筛选出所有不为null的元素
    val list = listOf(1,2,3,null,4)
    assertEquals(listOf(1,2,3,4),list.filterNotNull())
  • first

    返回第一个满足条件的元素,没有则抛出NoSuchElementException

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    val list = listOf(1,2,3,4)
    assertEquals(2,list.first { it > 1 })
    // firstOrNull: 返回第一个满足条件的元素,没有,则 返回Null
    val list = listOf(1, 2, 3, 4)
    assertEquals(null, list.firstOrNull { it > 5 })
    // find :同firstOrNull。返回第一个满足条件的元素,没有,则 返回Null
    val list = listOf(1,2,3,4)
    assertEquals(2,list.find { it > 1 })
    // findLast: 返回最后一个满足条件的元素,没有,则 返回Null
    val list = listOf(1,2,3,4)
    assertEquals(4,list.findLast { it > 1 })


    // last: 返回符合给定函数条件的最后一个元素,不存在则抛出NoSuchElementException
    val list = listOf(1, 2, 2, 4)
    assertEquals(4, list.last { it % 2 == 0 })
    // lastIndexOf: 返回指定元素的第一个索引位置,不存在返回-1
    val list = listOf(1, 2, 2, 4)
    assertEquals(2, list.lastIndexOf(2) )
    // lastOrNull: 返回符合给定函数条件的最后一个元素,不存在返回null
    val list = listOf(1, 2, 2, 4)
    assertNull( list.lastOrNull{ it >5})
  • single: 返回符合指定函数条件的单个元素,如果没有符合或者超过一个,则抛出异常。\

    1
    2
    3
    4
    5
    6
    val list = listOf(1, 2, 2, 4)
    assertEquals(4, list.single { it == 4 })

    // singleOrNull: 返回符合指定函数条件的单个元素,如果没有符合或者超过一个,则返回null
    val list = listOf(1, 2, 2, 4)
    assertEquals(null, list.singleOrNull { it == 2 })
  • flatMap: 遍历所有的元素,为每一个元素创建一个集合,最后把所有的集合放在一个集合中。

    1
    2
    val list = listOf(1, 2)
    assertEquals(listOf(1,2,2,4),list.flatMap { it -> listOf(it,it*2) })
  • flatten: 遍历一个单独的集合,包含给定嵌套集合里面的所有元素。

    1
    2
    val list = listOf(listOf(1,2), listOf(4,2), listOf(3), listOf(4))
    assertEquals(listOf(1,2,4,2,3,4), list.flatten())
  • fold: 将对集合从第一个到最后一个元素进行操作

    1
    2
    3
    4
    5
    6
    //这里是进行乘法操作
    val list = listOf(1, 2, 3, 4)
    assertEquals(48, list.fold(2) { total, next -> total * next })
    // foldRight: 跟fold操作一样,不过是从最后一个到到一个元素进行操作
    val list = listOf(1, 2, 3, 4)
    assertEquals(48, list.foldRight(2) { total, next -> total * next })
  • reduce: 与fold功能一样。但是,没有初始值。把集合从第一个到最后一个,按指定条件进行操作

    1
    2
    val list = listOf(1, 2, 2, 4)
    assertEquals(-7, list.reduce { total, next -> total -next })
  • get:获取索引所在的元素,没有则返回ArrayIndexOutOfBoundsException

    1
    2
    3
    4
    5
    6
    7
    8
    // getOrElse: 获取索引所在的元素,没有就返回默认值
    val list = listOf(1, 2, 4, 2, 3, 4)
    assertEquals(10, list.getOrElse(8, { _ -> 10 }))
    assertEquals(2, list.getOrElse(1, { _ -> 10 }))
    // getOrNull: 获取索引所在的元素,没有就返回nul
    val list = listOf(1, 2, 4, 2, 3, 4)
    assertEquals(null, list.getOrNull(8))
    assertEquals(4, list.getOrNull(2))
  • map: 返回一个每个元素都根据给定函数条件转换的数组

    1
    2
    3
    4
    5
    6
    7
    8
    val list = listOf(1, 2, 2, 4)
    assertEquals(listOf(2, 4, 4, 8), list.map{ it*2} )
    // mapIndexed: 功能同map,比map多了一个索引
    val list = listOf(1, 2, 2, 4)
    assertEquals(listOf(0, 2, 4, 4), list.mapIndexed { index, it -> if (index % 2 == 0) index * it else it })
    // mapNotNull: 同map。但是,元素转换不包含Null
    val list = listOf(1, 2,null, 2, 4)
    assertEquals(listOf(2, 4, 4, 8), list.mapNotNull { it?.times(2) })
  • max: 返回集合最大元素。不存在返回null

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    val list = listOf(1, 2, 2, 4)
    assertEquals(4, list.max())
    val list = emptyList<Int>()
    assertEquals(null, list.max())

    // maxBy:返回根据指定函数转换后,产生的最大值的原始元素(返回的还是原始元素)。如果没有元素,则返回null。
    val list = listOf(1, 2, 2, 4)
    assertEquals(1, list.maxBy { -it })
    // min:返回集合最小元素,不存在返回null
    val list = listOf(1, 2, 2, 4)
    assertEquals(1, list.min())
    // minBy: 返回根据指定函数转换后,产生的最小值的原始元素(返回的还是原始元素)。如果没有元素,则返回null。
    val list = listOf(1, 2, 2, 4)
    assertEquals(4, list.minBy { -it })
  • none: 如果没有任何元素与指定的函数条件匹配,则返回true。

    1
    2
    val list = mutableListOf(1, 2, 2, 4)
    assertTrue(list.none { it > 4 })
  • orEmpty: 如果没有任何元素与指定的函数条件匹配,则返回true。

    1
    2
    val list = mutableListOf(1, 2, 2, 4)
    assertTrue(list.none { it > 4 })
  • sorted:返回所有元素分类排序列表。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    val list = listOf(1, 4, 2, 2)
    assertEquals(listOf(1, 2, 2, 4), list.sorted())

    // sortBy:返回所有元素分类排序列表。顺序按照指定函数条件排列
    val list = listOf(1, 4, 2, 2)
    assertEquals(listOf(4,2,2,1), list.sortedBy { -it })

    // sortDescending:返回所有元素分类排序列表。顺序按降序排列
    val list = listOf(1, 4, 2, 2)
    assertEquals(listOf(4,2,2,1), list.sortedDescending())

    // sortedByDescending:返回所有元素分类排序列表。顺序按指定函数条件的降序排列
    val list = listOf(1, 4, 2, 2)
    assertEquals(listOf(1,2,2,4), list.sortedByDescending{ -it })
  • slice: 返回一个list中指定index的元素。

    1
    2
    3
    val list = listOf(1, 4, 2, 2)
    assertEquals(listOf(4,2,2), list.slice(1..3))
    assertEquals(listOf(1,4), list.slice(listOf(0,1)))
  • take: 返回从第一个元素开始的n个元素。

    1
    2
    val list = listOf(1, 4, 2, 2)
    assertEquals(listOf(1,4), list.take(2))
  • zip: 返回一个列表,该列表由两个集合中相同索引元素建立的元素对。这个列表长度为最短集合的长度。

1
2
val list = listOf(1, 4, 2, 2)
assertEquals(listOf(Pair(1,10),Pair(4,20),Pair(2,30)), list.zip(listOf(10,20,30)))
  • groupBy

    返回一个根据给定函数分组后的map, value为list

    1
    2
    val list = listOf(1, 2, 2, 4)
    assertEquals(mapOf("error" to listOf(1), "right" to listOf(2, 2, 4)), list.groupBy { if (it % 2 == 0) "right" else "error" })
  • associateBy

    通过指定的条件,把list转换成map,value为单元素

    2种,第一只转换map的key;第二map的key-value都转换

    1
    2
    3
    val list = listOf(1, 4, 2, 2)
    assertEquals(hashMapOf("key1" to 1, "key4" to 4, "key2" to 2), list.associateBy { it -> "key" + it })
    assertEquals(hashMapOf("key1" to "value1", "key4" to "value4", "key2" to "value2"), list.associateBy({ it -> "key" + it }, { it -> "value" + it }))

associateBy和groupBy区别

函数associateBy和groupBy构建来自由指定键索引的集合的元素的映射。key在keySelector参数中定义。

还可以指定可选的valueSelector来再选择定义将存储在map元素值中的内容。

区别

associateBy和groupBy之间的区别在于它们如何使用相同的键处理对象:

  • associateBy使用最后一个合适的元素作为
  • groupBy构建所有合适元素的列表并将其放入中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
data class StreamPractise(
val id: Int,
val name: String,
val age: Int
)

fun main() {
val l = listOf(StreamPractise(1, "hello", 19), StreamPractise(1, "cl", 31))
var res = l.associateBy { it.id }
println(res)
}
// {1=StreamPractise(id=1, name=cl, age=31)}

fun main() {
val l = listOf(StreamPractise(1, "hello", 19), StreamPractise(1, "cl", 31))
var res = l.groupBy { it.id }
println(res)
}
// {1=[StreamPractise(id=1, name=hello, age=19), StreamPractise(id=1, name=cl, age=31)]}

Map

  • getOrElse() 与 list 的工作方式相同:对于不存在的键,其值由给定的 lambda 表达式返回。

  • getOrDefault() 如果找不到键,则返回指定的默认值。

  • filter: 可以使用 filter() 函数来过滤 map 或其他集合。 对 map 使用 filter() 函数时, Pair 将作为参数的谓词传递给它。 它将使用谓词同时过滤其中的键和值。

    1
    2
    3
    val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11)
    val filteredMap = numbersMap.filter { (key, value) -> key.endsWith("1") && value > 10}
    println(filteredMap)
  • put()添加新的kv

  • putAll()要一次添加多个条目,请使用 putAll() 。它的参数可以是 Map 或一组 PairIterableSequenceArray

    1
    2
    3
    val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3)
    numbersMap.putAll(setOf("four" to 4, "five" to 5))
    println(numbersMap)
    • remove: 要从可变 Map 中删除条目,请使用 remove() 函数。 调用 remove() 时,可以传递键或整个键值对。 如果同时指定键和值,则仅当键值都匹配时,才会删除此的元素。
    1
    2
    3
    4
    5
    val numbersMap = mutableMapOf("one" to 1, "two" to 2, "three" to 3)
    numbersMap.remove("one")
    println(numbersMap)
    numbersMap.remove("three", 4) //不会删除任何条目
    println(numbersMap)
  • plusminus 操作

    由于需要访问元素的键,plus+)与 minus-)运算符对 map 的作用与其他集合不同。 plus 返回包含两个操作数元素的 Map :左侧的 Map 与右侧的 Pair 或另一个 Map 。 当右侧操作数中有左侧 Map 中已存在的键时,该条目将使用右侧的值(覆盖)。

    1
    2
    3
    4
    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 将根据左侧 Map 条目创建一个新 Map ,右侧操作数带有键的条目将被剔除。 因此,右侧操作数可以是单个键或键的集合: list 、 set 等。

    1
    2
    3
    val numbersMap = mapOf("one" to 1, "two" to 2, "three" to 3)
    println(numbersMap - "one")
    println(numbersMap - listOf("two", "four"))
  • containsKey, containsValue

  • isNotEmpty

  • sort map:根据键或者值排序

    1
    2
    3
    4
    5
    6
    7
    val mmp = mapOf(1 to "aone", 3 to "three", 2 to "two", 4 to "four")
    val sortedMap: SortedMap<Int, String> = mmp.toSortedMap(Comparator { o1, o2 ->
    println("o1=$o1,o2=$o2")
    if (o1 > o2) 1 else if (o1 < o2) -1 else 0
    })

    println(sortedMap) // {1=aone, 2=two, 3=three, 4=four}
  • ⭐️Convert Map to List

    1
    2
    3
    4
    5
    6
    7
    8
    val keyList = ArrayList(mmp.keys)
    val valueList = ArrayList(mmp.values)

    println("Key List: $keyList") // Key List: [1, 3, 2, 4]
    println("Value List: $valueList") // Value List: [aone, three, two, four]

    val list = mmp.toList().map { "${it.first}_${it.second}" }
    println("list=$list") // list=[1_aone, 3_three, 2_two, 4_four]
  • ⭐️Converting a List to Map in Kotlin

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     val user1 = User("John", 18, listOf("Hiking", "Running", "Reading"))
    val user2 = User("Sara", 25, listOf("Chess", "Music"))
    val user3 = User("Dave", 34, listOf("Games", "Programming"))
    val myList = listOf(user1, user2, user3)

    val myMap = myList.map { it.name to it }.toMap()
    println(myMap) // {John=User(name=John, age=18, hobbit=[Hiking, Running, Reading]), Sara=User(name=Sara, age=25, hobbit=[Chess, Music]), Dave=User(name=Dave, age=34, hobbit=[Games, Programming])}

    val amap = myList.associateBy { it.age }
    println(amap) // {18=User(name=John, age=18, hobbit=[Hiking, Running, Reading]), 25=User(name=Sara, age=25, hobbit=[Chess, Music]), 34=User(name=Dave, age=34, hobbit=[Games, Programming])}

Author: Mrli

Link: https://nymrli.top/2021/12/27/Kotlin集合、流式操作/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
开发方向-技术栈
NextPost >
开发过程中Mysql API记录
CATALOG
  1. 1. List
    1. 1.1. associateBy和groupBy区别
  2. 2. Map