Kotlin数组与集合

957 阅读15分钟

前言:本章主要介绍Kotlin数组与集合的基础知识,主要内容包含数组与集合的创建方法、遍历方式以及常用的集合操作符汇总。如发现有误之处,欢迎指正。

数组

1. 数组创建

1.1 普通数组Array

Kotlin中提供以下方式创建装箱类数组:

  • 使用arrayOf()方法创建
  • 使用Array构造函数创建
  • 使用arrayOfNulls(size)方法创建,初始值为null
Java
//创建长度为5,初始值为1到5的数组
int[] array = new int[]{1,2,3,4,5};
//创建长度为5的字符串数组
String[] array2 = new String[5];
kotlin
//1.创建长度为5,初始值为1到5的数组,值不能为null
val array1 = arrayOf(1, 2, 3, 4, 5)
//数组类型指定Int?,值可为null
val arrayNull = arrayOf<Int?>(1, 2, 3, 4, 5)

//2.创建长度为5,初始值是NO.1到NO.5的数组
val stringArray = Array(5) {"NO.${it + 1}"}

//3.创建长度为5,初始值为null的数组,方法里的泛型指定为T?
val arrayNull2 = arrayOfNulls<Int>(5)

1.2 基本数据类型数组

Arrays里有各种基本数据类型的数组类,比如说 IntArray,对应Java的int[]。kotlin中创建基本数据类型数组使用 intArrayOf()longArrayOf()xxxArrayof方法。

Javakotlin
int[]IntArray
short[]ShortArray
long[]LongArray
float[]FloatArray
double[]DoubleArray
char[]CharArray
//创建长度为5,初始值为1到5的int类型数组
//1.调用intArrayOf方法创建
val intArray = intArrayOf(1, 2, 3, 4, 5)
//2.构造函数方式创建
val intArray2 = IntArray(5) {it + 1}

注意:IntArray等基本数据类型数组与Array<Int>是完全不同的类型,并无继承关系,无法相互赋值。

2. 数组读写

  • 以数组下标的方式读写(与Java一样)
  • 调用set/get方法操作数组
  • 使用elementAt(index)等操作符访问数组元素
kotlin
//创建数组
val array1 = arrayOf(1, 2, 3, 4, 5)
//打印原数据
println("${array1.joinToString()}")//输出 1, 2, 3, 4, 5
//数组下标形式赋值
array1[0] = 9
//调用set方法赋值
array1.set(1, 8)

//数组下标形式获取值
println("${array1[0]}")//输出 9
//调用get方法获取值
println("${array1.get(0)}")//输出 9
println("${intArray.elementAt(0)}")//输出 9
println("${intArray.elementAtOrElse(10) { -1 }}")//输出 -1
println("${intArray.elementAtOrNull(10)}")//输出 null

提示:如果使用set/get方法读写数组,AS会提示建议使用第一种数组下标的方式

3. 数组遍历

  • 利用in关键字,遍历数组中的每一个元素;这种方法类似于Java的增强for循环,不同的是,Kotlin可以自动类型推导元素类型,因此Kotlin不需要写元素类型声明
  • 利用forEach()高阶函数,遍历数组中的每一个元素
  • Iterable迭代器方式
  • 利用区间 arr.indices(或者0..arr.size -1)获得每一个元素的索引,遍历数组中的每一个元素
Java
//方式一
for (int i = 0; i < array.length; i++) {
    //do something
}

//方式二
for (int i : array) {
    //do something
}
kotlin
//in关键字访问数组
for (i in array) {
    //do something
}

//利用forEach高阶函数
array.forEach { 
    //do something
}
//利用forEachIndexed高阶函数同时访问数组的索引和元素
array.forEachIndexed { index, i -> println("index= $index,value=$i") }

//Iterable迭代器方式
val iterator = array.iterator()
while (iterator.hasNext()) {
    println(iterator.next())
}

//利用区间获取数组索引
for (index in array.indices) {
    //do something
}
//同时访问数组的索引和元素
for ((index, value) in array.withIndex()) {
    //do something
}
//按迭代步数遍历数组
val array = arrayOf(1, 2, 3, 4, 5, 6)
for (index in array.indices step 2) {
    println(array[index]) //输出 1 3 5
}
//反向遍历数组
for (index in array1.size - 1 downTo 0) {
    println(array1[index]) //输出 6 5 4 3 2 1
}

4. 数组常用操作符

val array1 = arrayOf(5, 2, 1, 4, 3)

//1.数组转换操作
//转基本类型数组
val intArrayTest = array1.toIntArray()
//数组转list
val list = array1.toList()
//数组转map
val map = array1.associateBy { "key$it" }

//2.数组排序操作
//升序排列
array1.sort()
println(array1.joinToString()) //输出 1, 2, 3, 4, 5
//倒序排列
array1.sortDescending();
println(array1.joinToString()) //输出 5, 4, 3, 2, 1
//数组反转
array1.reverse()
println(array1.joinToString()) //输出 1, 2, 3, 4, 5

//3.数值类型数组统计操作
//最大值
val max = array1.maxOrNull()
//最小值
val min = array1.minOrNull()
//平均值,返回double类型
val average = array1.average()
println(max) //输出 5
println(min) //输出 1
println(average) //输出 3.0

//4.数组拷贝
//复制一个长度为6的新数组
val copyArray = array1.copyOf(6)
println(copyArray.joinToString()) //输出 1, 2, 3, 4, 5, null

//5.数组去重
val array2 = arrayOf(1, 2, 3, 4, 1)
//去重,返回一个新数组
val distinctArray = array2.distinct()
println(distinctArray.joinToString()) //输出 1, 2, 3, 4

//6.数组元素操作
//是否包含元素
val result = array2.contains(1)
println(result) //输出 true
//查找元素的索引(找到第一位元素则返回索引,找不到元素则返回-1)
val index = array2.indexOf(1)
val index2 = array2.indexOf(9)
println(index) //输出 0
println(index2) //输出 -1

小结:

  • Kotlin数组可划分为Array以及CharArrayIntArray等基本数据类型数组,两者无继承关系,不能相互赋值。
  • Kotlin提供Arrays.kt文件,里面含有大量的数组操作符,包括拷贝、去重等操作。与Java相比,大大方便开发者操作数组,减少工作量。

集合

1. 集合的分类

Kotlin中集合与Java最大的不同点是,kotlin集合分为只读集合和可变集合。

  • 只读集合在创建后就不能进行修改,不具有addremove等操作方法,只读集合包括ListSetMap
  • 可变集合继承只读集合类,在此基础上新增addremove等操作方法,可变集合包括MutableListMutableSetMutableMap及其实现类。MutableListMutableSetMutableMap类似于Java的ListSetMap集合类图
classDiagram
Iterable <|--  Collection
Iterable <|--  MutableIterable

Collection <|--  List
List <|--  MutableList
MutableList <|--  ArrayList

Collection <|--  Set
Set <|--  MutableSet
MutableSet <|--  HashSet
MutableSet <|--  LinkedHashSet

Collection <|--  MutableCollection
MutableIterable <|--  MutableCollection
MutableCollection <|--  MutableList
MutableCollection <|--  MutableSet

Map <|--  MutableMap
MutableMap <|--  HashMap
MutableMap <|--  LinkedHashMap

<<interface>> Iterable
Iterable: +iterator()
 
<<interface>> Collection
Collection : +int size
Collection : + isEmpty()
Collection : + contains()
Collection : + containsAll()

<<interface>> MutableIterable
MutableIterable : + iterator()

<<interface>> List
List : + get()
List : ....()
<<interface>> MutableList
MutableList : + set()
MutableList : + removeAt()
MutableList : ....()
<<interface>> MutableSet
class ArrayList{
 
}

<<interface>> Set
class HashSet{
 
}
class LinkedHashSet{
 
}

<<interface>> MutableCollection
MutableCollection : + add()
MutableCollection : + remove()
MutableCollection : + addAll()
MutableCollection : + removeAll()
MutableCollection : + clear()
<<interface>> Map
Map : +int size
Map : +Set keys
Map : +Collection values
Map : ...
Map : + isEmpty()
Map : + containKey()
Map : + containsValue()
Map : + get()
Map : ....()
<<interface>> MutableMap
MutableMap : + put()
MutableMap : + remove()
MutableMap : + putAll()
MutableMap : + clear()
MutableMap : ....()
class HashMap{
 
}
class LinkedHashMap{
 
}

2. List

List 是一个有序、元素可重复的列表,可通过索引(反映元素位置的整数)访问元素。

2.1 创建方式

kotlin提供以下方法创建List列表:

  • listOf():该函数返回不可变的List
  • mutableListOf():该函数返回可变的MutableList
  • arrayListOf():该函数返回可变的ArrayList
  • 使用构造函数方式List(size: Int, init: (index: Int) -> T)MutableList(size: Int, init: (index: Int) -> T)创建
//调用内置函数xxxOf方法创建
//创建空的不可变集合list,需指定类型
val list = listOf<Int>()
//创建1到3的list
val list2 = listOf(1, 2, 3)
//创建空的可变集合mutableList,需指定类型
val mutableList = mutableListOf<Int>()
//创建1到3的可变集合mutableList
val mutableList2 = mutableListOf(1, 2, 3)
//创建1到3的可变集合arrayList
val arrayList = arrayListOf(1, 2, 3)

// 创建1到5的不可变集合list
val list3 = List(5) { it + 1}
//创建1到5的可变集合mutableList
val mutableList3 = MutableList(5) { it + 1 }

//创建空List,等同于listOf<Int>()
val emptyList = emptyList<Int>()

疑问:在Kotlin中没找到对应的LinkedList实现类,据说在Kotlin 1.0把linkedListOf()这个方法给废弃掉了?

2.2 读写方式

  • 通过下标方式取值,可变的MutableList可使用下标方式直接赋值(类似于Java数组赋值)
  • 通过get方法取值,可变的MutableList可使用set方法赋值
  • 可变List可通过addremoveaddAllremoveAllremoveAt等增删方法操作List
  • 使用elementAt(index)等操作符访问List元素
//创建mutableList
val mutableList = mutableListOf(1, 2, 3)
//以下标方式取值
println(mutableList[0]) //输出 1
//以下标方式赋值
mutableList[0] = 4
println(mutableList.joinToString()) //输出 4, 2, 3

//以get方法取值
println(mutableList.get(0)) //输出 4
///以set方法赋值
mutableList.set(0, 5)
println(mutableList.joinToString()) //输出 5, 2, 3

//使用elementAt(index)取值
println(mutableList.elementAt(0)) //输出 5

与Java相比,kotlin还提供以下标索引的方式访问list元素(类似于Java的访问数组元素),且AS建议使用该方式访问list元素。

2.3 遍历方式

同上述数组的遍历方式

val list = listOf(1, 2, 3, 4, 5, 6)
//in关键字访问list
for (i in list) {
    //do something
}

//利用forEach高阶函数
list.forEach {
    //do something
}
//利用forEachIndexed高阶函数同时访问list的索引和元素
list.forEachIndexed { index, i -> println("index= $index,value=$i") }

//Iterable迭代器方式
val iterator = list.iterator()
while (iterator.hasNext()) {
    println(iterator.next())
}

//利用区间获取list索引
for (index in list.indices) {
    //do something
}
//同时访问list的索引和元素
for ((index, value) in list.withIndex()) {
    //do something
}
//按迭代步数遍历list
for (index in list.indices step 2) {
    println(list[index]) //输出 1 3 5
}
//反向遍历list
for (index in list.size - 1 downTo 0) {
    println(list[index]) //输出 6 5 4 3 2 1
}

3. Set

Set是无序、无重复元素的集合。如需使用有序的Set,可使用LinkedHashSet类型。

3.1 创建方式

kotlin提供以下方法创建Set集合:

  • setOf():该函数返回不可变的Set集合,传入元素参数时方法内部创建的是有序的LinkedHashSet类型
  • mutableSetOf():该函数返回可变的MutableSet集合,传入元素参数时方法内部创建的是有序的LinkedHashSet类型
  • hashSetOf():该函数返回可变、无序的HashSet集合
  • linkedSetOf():该函数返回可变、有序的LinkedSet集合
  • sortedSetOf():该函数返回可变、升序排列的TreeSet集合
//创建不可变的空集合list,需指定类型
val set = setOf<Int>()
//创建1到3的Set
val set2 = setOf(1, 2, 3, 1) //输出1 2 3
//创建可变的空集合mutableSet,需指定类型
val mutableSet = mutableSetOf<Int>()
//创建1到3的可变集合mutableList
val mutableSet2 = mutableSetOf(1, 2, 3)
//创建1到3的可变集合hashSet
val hashSet = hashSetOf(1, 2, 3)
//创建1到3的可变集合linkedHashSet
val linkedHashSet = linkedSetOf(1, 2, 3)
//创建1到3的可变集合treeSet
val treeSet = sortedSetOf(1, 3, 2) //输出 1 2 3
//创建空Set,等同于setOf<Int>()
val emptySet = emptySet<Int>()

3.2 读写方式

  • 可变集合可通过addremoveaddAllremoveAll等增删方法操作Set
  • 使用elementAt(index)等操作符访问Set元素

3.3 遍历方式

List遍历方式

4. Map

Map集合用于保存key-value对,其也被分为可变的和不可变的

4.1 创建方式

kotlin提供以下方法创建Map键值对:

  • mapOf():该函数返回不可变的Map集合
  • mutableMapOf():该函数返回可变的MutableMap集合
  • hashMapOf():该函数返回可变的HashMap集合
  • linkedMapOf():该函数返回可变的LinkedHashMap集合
  • sortedMapOf():该函数返回可变的TreeMap集合
//创建不可变的空map
val map = mapOf<String, Int>()

//创建不可变、有初始值的map(使用to关键字)
val map2 = mapOf("No.1" to 1, "No.2" to 2, "No.3" to 3)
//创建不可变、有初始值的map(直接传入Pair)
val map3 = mapOf(Pair("No.1", 1), Pair("No.2", 2), Pair("No.3", 3))

//创建可变、有初始值的mutableMap
val mutableMap = mutableMapOf("No.1" to 1, "No.2" to 2, "No.3" to 3, "No.4" to 4, "No.5" to 5)

//创建可变、有初始值的hashMap
val hashMap = hashMapOf("No.1" to 1, "No.2" to 2, "No.3" to 3)

//创建可变、有初始值的linkedMap
val linkedMap = linkedMapOf("No.1" to 1, "No.2" to 2, "No.3" to 3)

//创建可变、有初始值的treeMap
val treeMap = sortedMapOf("No.1" to 1, "No.2" to 2, "No.3" to 3)

4.2 读写方式

  • 以key为下标的方式读写,如map[key]Map的value值,而可变的MutableMap,可以直接通过mutableMap[key] = xxx的方式给value赋值
  • 通过get方法取value值,可变的MutableMap可通过put方法赋值
  • MutableMap还可以使用set操作符赋值
//创建可变、有初始值的mutableMap
val mutableMap = mutableMapOf("No.1" to 1, "No.2" to 2, "No.3" to 3)
//以下标方式直接取值
println(mutableMap["No.3"]) //输出 3
//以下标方式赋值
mutableMap["No.3"] = 0
println(mutableMap) //输出 {No.1=1, No.2=2, No.3=0}

//以get方法取值
println(mutableMap.get("No.3")) //输出 0
//以put方法赋值
mutableMap.put("No.3", 1)
println(mutableMap) //输出 {No.1=1, No.2=2, No.3=1}

//以操作符set方法赋值
mutableMap.set("No.3", 2)
println(mutableMap) //输出 {No.1=1, No.2=2, No.3=2}

//输出map的所有key
println(mutableMap.keys) //输出 [No.1, No.2, No.3]
//输出map的所有value
println(mutableMap.values) //输出 [1, 2, 2]

与Java相比,kotlin还提供以下标索引的方式访问map元素(类似于Java的访问数组元素),且AS建议使用该方式访问map元素。

4.3 遍历方式

  • 通过返回key-value对组成的Set来遍历map元素
  • 先遍历Map的key,再通过key获取value
  • 通过for-in循环直接访问key-value来遍历Map
  • 使用forEach高阶函数遍历Map
//创建不可变、有初始值的map
val map = mapOf("No.1" to 1, "No.2" to 2, "No.3" to 3)

//通过返回key-value对组成的Set来遍历`map`元素
for (entry in map) {
    println("${entry.key}->${entry.value}")
}

//先遍历`Map`的key,再通过key获取value
for (key in map.keys) {
    println("${key}->${map[key]}")
}

//通过`for-in`循环直接访问key-value来遍历`Map`
for ((key, value) in map) {
    println("${key}->${value}")
}

//使用`forEach`高阶函数遍历`Map`
map.forEach { println("${it.key}->${it.value}") }

常用操作符汇总

1.转换类

  • 转换成数组:toXXXArray()
  • 转换成ListtoList()/toMutableList()
  • 转换成MapassociateBy{...}
val list0 = listOf(1, 2, 3, 4, 5)
//转换成另一个不可变的新list
println(list0.toList()) // [1, 2, 3, 4, 5]
//转换成一个可变的新MutableList
println(list0.toMutableList()) // [1, 2, 3, 4, 5]
//转换成新数组
println(list0.toIntArray().joinToString()) // 1, 2, 3, 4, 5
//转换成新Map
println(list0.associateBy { "No.$it" }) //{No.1=1, No.2=2, No.3=3, No.4=4, No.5=5}

2.操作类

Kotlin提供六大类集合操作符,数组与集合的操作符基本雷同。下面以List的操作符举例:

2.1 元素操作符

  • contains(元素):检测是否包含指定的元素,如存在则返回true,不存在则返回false
  • elementAt(index):获取对应下标的元素,如下标越界,会抛出IndexOutOfBoundsException(下标越界)异常
  • elementAtOrElse(index,{...}):检测是否包含指定的元素,如存在则返回true,不存在则返回false
  • elementAtOrNull(index):获取对应下标的元素。若下标越界,返回null
  • getOrElse(index,{...}):获取对应下标的元素。若下标越界,返回指定的默认值(同elementAtOrElse
  • getOrNull(index)://获取对应下标的元素。若下标越界,返回null(同elementAtOrNull
  • first():获取第一个元素,若集合为空集合则会抛出NoSuchElementException异常
  • first{...}:获取第一个满足指定条件的元素,若找不到元素则会抛出NoSuchElementException异常
  • firstOrNull():获取第一个元素,若集合为空集合则会null
  • firstOrNull{...}:获取第一个满足指定条件的元素,若找不到元素则返回null
  • last():获取最后一个元素,若集合为空集合则会抛出NoSuchElementException异常
  • last{}:获取最后一个满足指定条件的元素,若找不到元素则会抛出NoSuchElementException异常
  • lastOrNull():获取最后一个满足指定条件的元素,若集合为空集合则会null
  • lastOrNull{...}:获取最后一个满足指定条件的元素,若集合为空集合则会null
  • indexOf(元素):返回第一个指定元素的下标,元素不存在则返回 -1
  • indexOfFirst{...}:返回第一个满足条件的元素的下标,元素不存在则返回 -1
  • lastIndexOf(元素):返回最后一个指定元素的下标,元素不存在则返回 -1
  • indexOfLast{...}:返回最后一个满足条件的元素的下标,元素不存在则返回 -1
  • forEach{...}:遍历元素
  • forEachIndexed{index,value}:遍历元素,获取元素下标以及元素
val list = listOf(1, 2, 3, 4, 5)
// 检测是否包含指定的元素,如存在则返回true,不存在则返回false
println(list.contains(3)) // true

//获取对应下标的元素,如下标越界,会抛出IndexOutOfBoundsException(下标越界)异常
println(list.elementAt(1)) // 2
//获取对应下标的元素。若下标越界,返回指定的默认值
println(list.elementAtOrElse(10) { -1 }) // -1
//获取对应下标的元素。若下标越界,返回null
println(list.elementAtOrNull(10)) // null

//获取对应下标的元素。若下标越界,返回指定的默认值(同elementAtOrElse)
println(list.getOrElse(10) { -1 }) // -1
//获取对应下标的元素。若下标越界,返回null(同elementAtOrNull)
println(list.getOrNull(10)) // null

//获取第一个元素,若集合为空集合则会抛出NoSuchElementException异常
println(list.first()) // 1
//获取第一个满足指定条件的元素,若找不到元素则会抛出NoSuchElementException异常
println(list.first { it > 2 }) // 3
//获取第一个元素,若集合为空集合则会null
println(list.firstOrNull()) // 1
//获取第一个满足指定条件的元素,若找不到元素则返回null
println(list.firstOrNull { it > 6 }) // null
//获取最后一个元素,若集合为空集合则会抛出NoSuchElementException异常
println(list.last()) // 5
//获取最后一个满足指定条件的元素,若找不到元素则会抛出NoSuchElementException异常
println(list.last { it > 2 })  // 5
//获取最后一个元素,若集合为空集合则会null
println(list.lastOrNull()) // 5
//获取最后一个满足指定条件的元素,若集合为空集合则会null
println(list.lastOrNull { it > 6 }) // null

//返回第一个指定元素的下标,元素不存在则返回 -1
println(list.indexOf(1)) // 0
//返回第一个满足条件的元素的下标,元素不存在则返回 -1
println(list.indexOfFirst { it > 1 }) // 1
//返回最后一个指定元素的下标,元素不存在则返回 -1
println(list.lastIndexOf(5)) // 4
//返回最后一个满足条件的元素的下标,元素不存在则返回 -1
println(list.indexOfLast { it > 0 }) // 4

//遍历元素
list.forEach { println(it) } // 1 2 3 4 5
//遍历元素,获取元素下标以及元素
list.forEachIndexed { index, i -> println("$index:$i") } // 0:1 1:2 2:3 3:4 4:5

2.2 顺序操作符

  • sorted():升序排列,返回新的list
  • sortedBy{...}:按条件排列,不满足条件的放在前面,满足条件的放在后面,返回新的list
  • sortedDescending():降序排序,返回新的list
  • sortedByDescending{...}:按条件排列,满足条件的放在前面,不满足条件的放在后面,返回新的list
  • reversed():反序,返回新的list
  • sortedWith(Comparator):按自定义条件规则排序,返回新的list
val list2 = listOf(3, 2, 1, 4, 5)
//升序排列,返回新的list
println(list2.sorted()) // [1, 2, 3, 4, 5]
//按条件排列,不满足条件的放在前面,满足条件的放在后面,返回新的list
println(list2.sortedBy { it in 2..4 }) // [1, 5, 3, 2, 4]
//降序排序,返回新的list
println(list2.sortedDescending()) // [5, 4, 3, 2, 1]
//按条件排列,满足条件的放在前面,不满足条件的放在后面,返回新的list
println(list2.sortedByDescending { it in 2..4 }) // [3, 2, 4, 1, 5]
//反序,返回新的list
println(list2.reversed()) // [5, 4, 1, 2, 3]

val stringList = listOf("aaa", "b", "cc", "d")
//定义按字符串长度升序排列规则
val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
//按自定义条件规则排序,返回新的list
println(stringList.sortedWith(lengthComparator)) // [b, d, cc, aaa]

2.3 映射操作符

  • map{...}:每个元素按特定的方法转换,组成新的list
  • mapNotNull{...}:同map{}函数,只是过滤掉转换之后为null的元素,组成新的list
  • mapIndexed{...}:每个元素按特定的方法转换,可以操作元素的下标,组成新的list
  • mapIndexedNotNull{...}:同mapIndexed{}函数,只是过滤掉转换之后为null的元素,组成新的list
  • flatMap{...}:根据条件合并两个集合,组成新的list
  • groupBy{...}:分组,根据条件把集合拆分为为一个Map<K,List>类型的集合
val list3 = listOf(3, 2, 1, 4, 5)
//每个元素按特定的方法转换,组成新的list
println(list3.map { "No.$it" }) // [No.3, No.2, No.1, No.4, No.5]
//同map{}函数,只是过滤掉转换之后为null的元素,组成新的list
println(list3.mapNotNull { if (it > 1) "No.$it" else null }) // [No.3, No.2, No.4, No.5]
//每个元素按特定的方法转换,只是其可以操作元素的下标,组成新的list
println(list3.mapIndexed { index, i -> "$index:No.$i" }) // [0:No.3, 1:No.2, 2:No.1, 3:No.4, 4:No.5]
//同mapIndexed{}函数,只是过滤掉转换之后为null的元素,组成新的list
println(list3.mapIndexedNotNull { index, i -> if (i > 1) "$index:No.$i" else null }) // [0:No.3, 1:No.2, 3:No.4, 4:No.5]
//每个元素根据条件以集合形式转换,组成新的list
println(list3.flatMap { listOf(it, "No.$it")}) // [3, No.3, 2, No.2, 1, No.1, 4, No.4, 5, No.5]
//分组,根据条件把集合拆分为为一个Map<K,List>类型的集合
println(list3.groupBy { if (it > 3) "bigData" else "smallData" }) // {smallData=[3, 2, 1], bigData=[4, 5]}

2.4 生产操作符

  • plus():合并两个集合的元素,组成一个新的list。也可以使用符号+
  • zip():两个集合的元素组成一个Pair类型元素,返回一个新的list(以长度小的原集合为准)
  • unzip():把Pair类型的集合拆分成两个集合,返回一个Pair类型
  • zipWithNext():集合中前一个元素与后一个元素组成Pair元素,返回一个新的list
  • partition{...}:按条件拆分成两个集合,返回一个Pair类型
val list4 = listOf(1, 2, 3, 4, 5)
val list5 = listOf(6, 7)
//合并两个集合的元素,组成一个新的list。也可以使用符号+
println(list4.plus(list5))// [1, 2, 3, 4, 5, 6, 7]
println(list4 + list5)// [1, 2, 3, 4, 5, 6, 7]
//两个集合的元素组成一个Pair类型元素,返回一个新的list(以长度小的原集合为准)
println(list4.zip(list5))// [(1, 6), (2, 7)]

val list6 = listOf(Pair(1, "a"), Pair(2, "b"), Pair(3, "c"))
//把Pair类型的集合拆分成两个集合,返回一个Pair类型
println(list6.unzip()) // ([1, 2, 3], [a, b, c])

//集合中前一个元素与后一个元素组成Pair元素,返回一个新的list
println(list4.zipWithNext())// [(1, 2), (2, 3), (3, 4), (4, 5)]
//按条件拆分成两个集合,返回一个Pair类型
println(list4.partition { it == 4 }) // ([4], [1, 2, 3, 5])

2.5 过滤操作符

  • filter{...}:过滤不满足条件的元素,返回一个新的list
  • filterIndexed{...}:过滤不满足条件的元素,可操作元素下标,返回一个新的list
  • filterNot{...}:与filter{}相反,过滤满足条件的元素,返回一个新的list
  • filterNotNull():过滤为null的元素,返回一个新的list
  • filterNotNullTo():过滤null的元素,并添加到指定list(传入的list必须为可变集合)
  • take():取前N个元素,组成新的list
  • takeWhile{...}:遍历集合,从第一个元素开始遍历集合,当第一个出现不满足条件元素的时候,退出遍历,把满足条件所有元素组成的集合返回。
  • takeLast():取后N个元素,组成新的list
  • takeLastWhile{...}:遍历集合,从最后一个元素开始遍历集合,当第一个出现不满足条件元素的时候,退出遍历,把满足条件所有元素组成的集合返回。
  • drop():过滤前N个元素,返回一个新的list
  • dropWhile{...}:遍历集合,从第一个元素开始遍历集合,当第一个出现不满足条件元素时,添加到新list,并且后续遍历的元素不做条件判断直接添加到新list后返回(与takeWhile{}函数相反)
  • dropLast():过滤后N个元素,返回一个新的list
  • dropLastWhile{...}:遍历集合,从最后一个元素开始遍历集合,当第一个出现不满足条件元素时,添加到新list,并且前面的元素不做条件判断直接添加到新list后返回(takeLastWhile{}函数相反)
  • distinct():过滤重复元素,返回一个新的list
  • distinctBy{...}:根据操作元素后的结果去除重复元素
  • slice():取指定区间下标的元素,返回一个新的list,如指定的区间超过list下标则会抛出IndexOutOfBoundsException(数组越界)异常
val list7 = listOf(1, 2, 3, 4, 5, 2)
//过滤不满足条件的元素,返回一个新的list
println(list7.filter { it > 1 }) // [2, 3, 4, 5, 2]
//过滤不满足条件的元素,可操作元素下标,返回一个新的list
println(list7.filterIndexed { index, i -> index == 0 || i == 2 }) // [1, 2, 2]
//与filter{}相反,过滤满足条件的元素,返回一个新的list
println(list7.filterNot { it > 1 }) // [1]

val listNull = listOf(1, 2, 3, 4, 5, 2, null)
//过滤为null的元素,返回一个新的list
println(listNull.filterNotNull()) // [1, 2, 3, 4, 5, 2]
val list8 = mutableListOf(0)
//过滤null的元素,并添加到指定list(传入的list必须为可变集合)
println(listNull.filterNotNullTo(list8)) // [0, 1, 2, 3, 4, 5, 2]

//取前N个元素,组成新的list
println(list7.take(2)) // [1, 2]
//遍历集合,从第一个元素开始遍历集合,当第一个出现不满足条件元素的时候,退出遍历。然后把满足条件所有元素组成的集合返回。
println(list7.takeWhile { it < 4 }) // [1, 2, 3]
//取后N个元素,组成新的list
println(list7.takeLast(2)) // [5, 2]
//遍历集合,从最后一个元素开始遍历集合,当第一个出现不满足条件元素的时候,退出遍历,把满足条件所有元素组成的集合返回。
println(list7.takeLastWhile { it < 4 }) // [2]

//过滤前N个元素,返回一个新的list
println(list7.drop(2)) // [3, 4, 5, 2]
//遍历集合,从第一个元素开始遍历集合,当第一个出现不满足条件元素时,添加到新list,并且后续遍历的元素不做条件判断直接添加到新list后返回(与takeWhile{…}函数相反)
println(list7.dropWhile { it < 4 }) // [4, 5, 2]
//过滤后N个元素,返回一个新的list
println(list7.dropLast(2)) // [1, 2, 3, 4]
//遍历集合,从最后一个元素开始遍历集合,当第一个出现不满足条件元素时,添加到新list,并且后续遍历的元素不做条件判断直接添加到新list后返回(takeLastWhile{…}函数相反)
println(list7.dropLastWhile { it < 4 }) // [1, 2, 3, 4, 5]

val list9 = listOf(1, 2, 3, 4, 5, 1, 2)
//过滤重复元素,返回一个新的list
println(list9.distinct()) // [1, 2, 3, 4, 5]
//根据操作元素后的结果去除重复元素
println(list9.distinctBy { it }) // [1, 2, 3, 4, 5]
println(list9.distinctBy { it < 3 }) // [1, 3]
//取指定区间下标的元素,返回一个新的list,如指定的区间超过list下标则会抛出IndexOutOfBoundsException(数组越界)异常
println(list9.slice(0..2)) // [1, 2, 3]
val list10 = listOf(1, 3)
println(list9.slice(list10)) // [2, 4]

2.6 统计操作符

  • maxOrNull():获取集合中的最大值,如果是空集合,则返回null
  • maxByOrNull{...}:获取方法处理后返回结果最大值对应的那个元素的初始值,如果是空集合,则返回null
  • maxOf{...}:获取方法处理后返回结果最大值,如果是空集合,则会抛出NoSuchElementException异常
  • maxOfOrNull{...}:获取方法处理后返回结果最大值,如果是空集合,则返回null
  • minOrNull():获取集合中的最小值,如果是空集合,则返回null
  • minByOrNull{...}:获取方法处理后返回结果最小值对应的那个元素的初始值,如果是空集合,则返回null
  • minOf{...}:获取方法处理后返回结果最小值,如果是空集合,则会抛出NoSuchElementException异常
  • minOfOrNull{...}:获取方法处理后返回结果最小值,如果是空集合,则返回null
  • sum():返回数值集合中的元素累加结果
  • sumOf{...}:根据元素运算操作后的结果,然后根据这个结果计算出累加的值。
  • average():计算集合的平均值,返回Double类型
  • reduce{...}:从集合中的第一个元素到最后一个元素的指定操作, 如果是空集合,则会抛出UnsupportedOperationException异常
  • reduceIndexed{...}:同reduce{},只是可以操作元素的下标
  • reduceOrNull{...}:从集合中的第一个元素到最后一个元素的指定操作,如果是空集合,则会返回null
  • reduceIndexedOrNull{...}:同reduceOrNull{},只是可以操作元素的下标
  • reduceRight{...}:从集合中的最后一个元素到第一个元素的指定操作, 如果是空集合,则会抛出UnsupportedOperationException异常
  • reduceRightIndexed{...}:同reduceRight{},只是可以操作元素的下标
  • reduceRightOrNull{...}:从集合中的最后一个元素到第一个元素的指定操作,如果是空集合,则会返回null
  • reduceRightIndexedOrNull{...}:同reduceRightOrNull{},只是可以操作元素的下标
  • fold(){...}:同reduce{},只是如果是空集合则返回指定的初始值
  • foldRight(){...}:同reduceRight{},只是如果是空集合则返回指定的初始值
  • any():判断是不是一个集合,若是,则再判断集合是否为空,若为空则返回false,反之返回true。若不是集合,则返回hasNext
  • any{...}:判断集合中是否存在满足条件的元素。若存在则返回true,反之返回false
  • all{...}://判断集合中的所有元素是否都满足条件。若是则返回true,反之则返回false
  • none()://判断是不是一个集合,若是,则再判断集合是否为空,若为空则返回true,反之返回false。若不是集合,则返回!hasNext(与any()相反)
  • none{...}:判断集合中的所有元素是否都不满足条件。若是则返回true,反之则返回false(与all{}相反)
val list11 = listOf(1, 2, 3, 4, 5)
val emptyList = emptyList<Int>()
//获取集合中的最大值,如果是空集合,则返回null
println(list11.maxOrNull()) // 5
//获取方法处理后返回结果最大值对应的那个元素的初始值,如果是空集合,则返回null
println(list11.maxByOrNull { it + 1 }) // 5
//获取方法处理后返回结果最大值,如果是空集合,则会抛出NoSuchElementException异常
println(list11.maxOf { it + 1 }) // 6
//获取方法处理后返回结果最大值,如果是空集合,则返回null
println(list11.maxOfOrNull { it + 1 }) // 6

//获取集合中的最小值,如果是空集合,则返回null
println(list11.minOrNull()) // 1
//获取方法处理后返回结果最小值对应的那个元素的初始值,如果是空集合,则返回null
println(list11.minByOrNull { it + 1 }) // 1
//获取方法处理后返回结果最小值,如果是空集合,则会抛出NoSuchElementException异常
println(list11.minOf { it + 1 }) // 2
//获取方法处理后返回结果最小值,如果是空集合,则返回null
println(list11.minOfOrNull { it + 1 }) // 2

//返回数值集合中的元素累加结果
println(list11.sum()) // 15
//根据元素运算操作后的结果,然后根据这个结果计算出累加的值。
println(list11.sumOf { it + 1 }) // 20

//计算集合的平均值,返回Double类型
println(list11.average()) // 3.0

//从集合中的第一个元素到最后一个元素的指定操作, 如果是空集合,则会抛出UnsupportedOperationException异常
println(list11.reduce { result, next -> result + next }) // 15
//同reduce{},只是可以操作元素的下标
println(list11.reduceIndexed { index, result, next -> index + result + next }) // 25
//从集合中的第一个元素到最后一个元素的指定操作,如果是空集合,则会返回null
println(list11.reduceOrNull { result, next -> result + next }) // 15
//同reduceOrNull{},只是可以操作元素的下标
println(list11.reduceIndexedOrNull { index, result, next -> index + result + next }) // 25

//从集合中的最后一个元素到第一个元素的指定操作, 如果是空集合,则会抛出UnsupportedOperationException异常
println(list11.reduceRight { result, next -> result + next }) // 15
//同reduceRight{},只是可以操作元素的下标
println(list11.reduceRightIndexed { index, result, next -> index + result + next }) // 21
//从集合中的最后一个元素到第一个元素的指定操作,如果是空集合,则会返回null
println(list11.reduceRightOrNull { result, next -> result + next }) // 15
//同reduceRightOrNull{},只是可以操作元素的下标
println(list11.reduceRightIndexedOrNull { index, result, next -> index + result + next }) // 21

//同reduce{},只是如果是空集合则返回指定的初始值
println(list11.fold(6) { result, next -> result + next })// 21
println(emptyList.fold(6) { result, next -> result + next })// 6
//同reduceRight{},只是如果是空集合则返回指定的初始值
println(emptyList.foldRight(6) { result, next -> result + next })// 6

//判断是不是一个集合,若是,则再判断集合是否为空,若为空则返回false,反之返回true。若不是集合,则返回hasNext
println(list11.any())// true
//判断集合中是否存在满足条件的元素。若存在则返回true,反之返回false
println(list11.any { it > 2 })// true
//判断集合中的所有元素是否都满足条件。若是则返回true,反之则返回false
println(list11.all { it > 2 })// false
//判断是不是一个集合,若是,则再判断集合是否为空,若为空则返回true,反之返回false。若不是集合,则返回!hasNext(与any()相反)
println(list11.none())// false
//判断集合中的所有元素是否都不满足条件。若是则返回true,反之则返回false
println(list11.none { it > 2 })// false

小结:

  • 与Java最大不同点是,Kotlin的集合分为可变集合与不可变集合
  • Kotlin中,List/Map可使用以索引下标/key直接访问的方式,类似于Java的数组的访问方式。
  • Kotlin提供大量的操作符,方便开发者操作数组与集合。数组操作符大部分放在_Arrays.kt文件,而集合操作符大部分在_Collections.kt文件,两者操作符基本雷同。