在 Java 类库中有一套相当完整的容器集合类来持有对象。Kotiin 没有去重复造轮子,而是在 Java 类库的基础上进行了改造和扩展,引入了不可变集合类,同时扩展了大量方便实用的功能,这些功能的 API 都在 kotlin.collections 包下面。
另外,在 Kotlin 的集合类中不仅仅能持有普通对象,而且能够持有函数类型的变量。
val funlist: List<(Int) -> Boolean> = listOf({
it -> it % 2 == 0 },
{
it -> it % 2 == 1 })
其中, (Int)->Boolean是一个从Int 映射到Boolean的函数。而这个时候,我们可以在代码里选择调用哪个函数:
val list = listOf(1, 2, 3, 4, 5, 6, 7)
val filter1 = list.filter(funlist[0])
val filter2 = list.filter(funlist[1])
println("filter1==$filter1")
println("filter2==$filter2")
//传入第1个函数funlist[O],返回[2, 4, 6]
//传入第2个函数funlist[1],返回[1,3, 5, 7]
集合类存放的都是对象的引用,而非对象本身,我们通常说的集合中的对象指的是集合中对象的引用( reference )。
Kotlin 的集合类分为:可变集合类( Mutable)与不可变集合类( Immutable) 。
集合类主要有3种: List(列表)、Set(集)和Map(映射)
从数据结构的本质上来看,其实List中的下标就是Key,只不过Key是有序 的Int类型,所以说List也可以说是一种特殊的Map数据结构。 而Set也是Key为Int类 型,但是 Value 值是不能重复的特殊 Map。
List 列表分为只读不可变的 List 和可变 MutableList (可写入、删除数据)。List列表的类型层次结构如图
Set 集也分为不可变 Set 和可变 MutableSet (可写入、删除数据)。 Set 集合的类型层次结构如图
Kotlin 中的 Map 与 List、Set 一样,Map 也分为只读 Map 和可变 MutableMap (可写入、 删除数据)。 Map类型的层次结构如图
Kotiin 中分别使用 listOf()、setOf()、mapOf() 函数创建不可变的 List列表容器、Set集容器、Map 映射容器。使用 mutableListOf()、 mutableSetO叹)、mutableMapOf()函数来创建可变的 MutableList 列表容器、MutableSet 集容器、MutableMap 映射容器,分别如图:
代码
//创建不可变 List
val list = listOf(1, 2, 3, 4, 5, 6, 7)
//创建可变MutableList
val mutableList = mutableListOf(”a”,”b”,”c”)
//创建不可变 Set
val set = setOf(1, 2, 3, 4, 5, 6, 7)
//创建可变 MutableSet
val mutableSet = mutableSetOf("a","b","c")
//创建不可变 Map
val map = mapOf(1 to "a",2 to "b",3 to "c")
//创建可变 MutableMap
val mutableMap = mutableMapOf(1 to "X",2 to "Y",3 to "Z")
如果创建没有元素的空 List,使用 listOf()即可。不过这个时候,变量的类型不能省略,需要显式声明 ,否则会报错
val emptyList : List<Int> = listOf() //显式声明 List 的元素-类型为 Int
val emptySet : Set<Int> = setOf() //显式声明 Set 的元素类型为 Int
val emptyMap: Map<Int, String>= mapOf(}//显式声明Map的元素类型为Int, String键值对
List、Set 类继承了 Iterable 接口,里面扩展了 forEach 函数来送代遍历元素;同样,Map 接口中也扩展了 forEach 函数来送代遍历元素。
list.forEach {
//List 中的 forEach
println(it)
}
set.forEach {
//Set 中的 forEach
println(it)
}
map.forEach {
//Map 中的 forEach
println(”K= ${
it.key}, V= ${
it.value}") //Map里面的对象是Map.Entry
}
forEach() 函数签名如下 :
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit
public inline fun <K, V> Map<out K, V>.forEach(action : (Map.Entry<K, V>)-> Unit) : Unit
在 Iterable 和 Map 中, forEach 函数都是一个内联 inline 函数
在迭代遍历元素的时候访问 index 下标,在 List 和 Set 中可以使用 下面的 forEachlndexed 函数
//带下标index来遍历 List
list.forEachindexed {
index, value ->
println (” list index = ${
index} , value = ${
value}” )
}
//带下标 index 来遍历 Set
set.forEachindexed {
index, value ->
println (” set index = ${
index} , value = ${
value}” )
}
其中,第 1 个参数是 index,第 2 个参数是 value
forEachlndexed 函数签名如下 :
public inline fun <T> Iterable<T> .forEachindexed(action : (index : Int , T)-> Unit): Unit
Map 的元素是 Entry 类型,由 entries属性持有
val entries : Set<Entry<K, V>>
这个 Entry类型定义如下:
public interface Entry<out K, out V> {
public val key: K //键值对的Key
public val value: V //键值对的Value
}
我们可以直接访问 entries 属性获取该 Map 中的所有键/值对的 Set。 代码示例如下:
>>> val map= mapOf(”x” to 1,”Y” to 2, ”z" to 3) //声明并初始化一个Map
>>> map
{
x=1 , y=2, z=3}
>>> map.entries
[x=1, y=2, z=3]
这样就可以遍历这个 Entry 的 Set 了 :
//遍历 entries 中的元素
>>> map .entries . forEach ({
println (”key=”+ it . key + ” value=”+ it.value)})
key=x value=1
key=y value=2
key=z value=3
使用 map 函数,可以把集合中的元素依次使用给定的转换函数进行映射操作,元素映射之后的新值会存入一个新的集合中,并返回这个新集合。
在 List、 Set 继承的 Iterable 接口和 Map 接口中,都提供了这个 m叩函数。使用 map 函数的代码示例如下 :
val list = listOf(1, 2, 3, 4, 5, 6, 7)//声明并初始化一个 List
val set = setOf(1, 2, 3, 4, 5, 6, 7)//声明并初始化一个 Set
val map = mapOf(1 to "a", 2 to "b", 3 to "c")//声明并初始化一个Map
//map函数对每个元素进行乘方操作,返回[1, 4, 9, 16, 25, 36, 49]
list.map {
it *it }
//map 函数对每个元素进行加 1操作,返回[2, 3, 4, 5, 6, 7, 8]
set.map{
it + 1 }
//map 函数对每个元素后加上字符$,返回[a$,b$, c$]
map .map{
it.value +"$" }
map 函数的签名如下 :
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R) : List<R>
public inline fun <K, V, R> Map<out K, V> .map (transform : (Map.Entry<K, V>) 一> R) : List<R>
这里的 R 类型是映射之后的数据类型,我们也可以传入一个 List:
val strlist = listOf("a","b","c")
//map 函数 , 每个元素 it 映射之后返回一个List,这个List 中有 4 个元素,分别是 it+1,
//it+2,it+3,it+4
strlist.map {
it -> listOf(it + 1, it + 2, it + 3, it + 4) }
//返回结果如下 :
[[a1, a2, a3, a4], [b1, b2, b3, b4] , [c1, c2, c3, c4]] //嵌套 List
Kotlin 中还提供了 一个 flatten()函数,效果是把嵌套的 List 结构“平铺”,变成一层 的 结构,代码示例如下 :
strlist.map {
it 一> listOf(it + 1, it+ 2, it+ 3, it + 4) }.flatten()
//输出如下 :
[a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4]
flatMap 函数是 map 和 flat两个函数的“复合逻辑”,代码如下 :
strlist.flatMap {
it -> listOf(it + 1, it + 2, it + 3, it + 4) }
输出同上面铺开的形式
首先,有一个 Student 对象,使用数据类来声明如下 :
data class Student (var id : Long, var name: String , var age : Int, var score :Int) {
override fun toString() : String {
//覆盖写 toString()函数
return "Student(id=$id, name='$name', age=$age, score=$score)"
}
}
创建一个持有 Student 对象 的 List:
//创建一个持有 Student对象 List
val studentList = listOf(
Student(l,”Jack”, 18, 90) ,
Student(2,”Rose”, 17, 80) ,
Student(3,”Alice”, 16, 70)
}
这个时候,如果我们想要过滤出年龄大于等于 18 岁的学生,代码可以这样写 :
//过滤出 studentList 中年龄大于等于 18 岁的Student 对象
studentList.filter{
it.age >= 18 }
输出如下:
[Student(id=1, name='Jack', age=18, score=90)]
如果想要过滤出分数小于 80 分的学生,代码如下 :
//过滤出 studentList 中分数小于 80 分的 Student 对象
studentList.filter{
it.score < 80 }
输出如下:
[Student (id=3 ,name='Alice', age=16, score=70)]
另外,如果想要通过访问下标来过滤,可以使用 filterlndexed()函数
val list= listOf(l, 2, 3, 4, 5, 6, 7)
list.filterindexed {
index, it -> index % 2 == 0 && it > 3 }
filterlndexed()函数签名如下 :
public inline fun <T> Iterable<T>.filterindexed(predicate: (index: Int, T)-> Boolean) : List<T>
Kotlin集合类中提供了倒序排列集合元素的函数 reversed(),代码示例如下:
val list = listOf(1, 2, 3, 4, 5, 6, 7)
val set= setOf(1,3,2)
list.reversed() //倒序函数,返回[7, 6, 5, 4, 3, 2, 1]
set.reversed() //倒序函数,返回[2, 3, 1]
这个 Iterable 的扩展函数 reversed()是直接调用的 java.util.Collections.reverse()方法。其 相关代码如下:
public fun <T> Iterable<T> . reversed() : List<T> {
if (this is Collection && s工ze <= 1) return toList ()
val list = toMutableList ()
list.reverse() //调用Java中List类型的reverse()方法 return list
}
public fun <T> MutableList<T>.reverse() : Unit {
java.util.Collections .reverse(this)
}
升序排序函数是 sorted(),实例代码如下:
>>> list.sorted()
(1, 2, 3, 4, 5, 6, 7]
>> set.sorted()
(1, 2, 3]
Kotlin 中的这个 sorted()函数也是直接调用 Java的 API来实现的,相关代码如下:
public fun <T : Comparable<T> Iterable<T> . sorted() : List<T> {
if (this is Collection) {
if (size <= 1) return this.toList()
@Suppress (” UNCHECKED_CAST” )
return(toTypedArray<Comparable<T> () as Array<T>) .apply {
sort()} .asList()
}
return toMutableList() .apply {
sort() }
}
其背后调用的是 Java.util.Arrays.sort()方法 :
public fun <T> Array<out T> . sort() : Unit {
if (size> 1) java.util.Arrays.sort(this)//调用 Java 中 Arrays类型的 sort芳法
}
如果我们想对一个 List列表进行元素去重,可以直接调用 distinct()函数:
val dupList = listOf(1, 1, 2, 2, 3, 3, 3)
dupList.distinct() //去重函数, 返回[1,2, 3]
Kotlin 的集合类中还提供了许多功能丰富的 API,可以参考 官方 API 文档