Kotlin——高级篇(四):集合(Array、List、Set、Map)基础

在实际的项目开发中,集合的运用能够说是多不胜数。不过Kotlin中的集合运用和Java中仍是有很大的差异,他们二者之间,除了集合的类型相同之外,还包含集合的初始化的不一样,以及Kotlin对于集合封装特别多的高阶函数以供咱们能更简单、更快捷的编写代码。不过在讲解集合以前,我先会对Kotlin中的数组类型作出一个讲解,你们能够当作是对数组Array<T>的一个温故。html

目录

1、数组类型

Kotlin数组类型不是集合中的一种,可是它又和集合有着太多类似的地方。而且数组和集合能够互换。而且在初始化集合的时候也能够传入一个数组。用于数组类型在前面的章节已经讲解过了,这里就不在多作累述。有兴趣的朋友能够去看我前面关于数据类型的文章。
Kotlin——初级篇(三):数据类型详解git

这里只介绍几个经常使用的方法。其实在文章的后面,也对这些方法作出了讲解。github

  • arr[index]的获取元素。
  • arr.component1() ... arr.component5()获取数组的前5个元素。一样适用与集合。
  • arr.reverse()反转元素。
  • 至于其余处理的元素,在文章的尾部都有说明。这也是我把数组类型与集合类型放在同一文章讲解的缘由。

例1:使用componentX()函数数组

val arr = arrayOf("1",2,3,4)

println(arr.component1())
println(arr.component3())

// 程序崩溃,由于元素只有4个,因此在不肯定元素个数的状况,慎用这些函数,仍是使用遍历安全些。
println(arr.component5())

输出结果:安全

1
3

例2 :反转元素ide

val arr = arrayOf("1",2,3,4)
arr.reverse()

// 文章后面会讲解forEach高阶函数。比for循环简洁多了
for (index in arr){
    print("$index \t")
}

输出结果:函数

4   3   2   1

2、集合类型

  • Kotlin中的集合和其余语言不一样的是,Kotlin集合可分为可变和不可变集合。
  • Kotlin中,集合类型包含三种类型:它们分别是:ListSetMap,这三种类型都有几个共通点:
    1. 它们都是接口,并非实际的类。
    2. 它们都继承至Collection<out E>接口,而Collection<out E>又继承与Iterable<out T>接口。它们几乎上只实现了isEmpty()、size属性、get()、contains()等方法。这一点和Java相似。
    3. 这三种集合类型分别有存在MutableList<E>、MutableSet<E>、MutableMap<K,V>接口,这些接口中提供了改变、操做集合的方法。例如add()clear()remove()等函数。

有以上三点咱们可出,在定义集合类型变量的时候若是使用List<E>Set<E>Map<K,V>声明的时候该集合则是不可变集合,而使用MutableList<E>MutableSet<E>MutableMap<K,V>的时候该集合才是可变类型集合。这里我就不提供源码来分析了,有兴趣的能够看一看源码!源码在kotlin\collections\Collections.kt文件post

下面对几个集合类型进行一一的讲解。this

2.一、List类型

咱们知道,一个接口是不能直接实例化的,那咱们要初始化一个怎么作呢?其实Kotlin给咱们提供了相应的标准库函数去处理。code

  • 声明并初始化List 的集合:使用 listOf(..)函数
  • 声明并初始化MutableList 的集合:使用 mutableListOf(..)函数

例1:使用listOf()初始化不可变的List类型集合

val arr = arrayOf("1","2",3,4,5)   
val list1 = listOf(1,2,"3",4,"5")                // 随意建立         
val list2 = listOf<String>("1","2","3","4","5")  // 肯定元素的值类型
val list3 = listOf(arr)                          // 可传入一个数组

如下代码是错误的。由于List<E>只能是不可变集合。而add、remove、clear等函数时MutableList中的函数
list1.add() 
list1.remove
...

// 遍历
for(value in list1){
    print("$value \t")
}

输出结果:

1   2   3   4   5

例2:使用mutableListOf()初始化不可变的List类型集合

val arr = arrayOf("1",2,3,4)
val mutableList1 = mutableListOf(1,2,"3",4,"5")                // 随意建立         
val mutableList2 = mutableListOf<String>("1","2","3","4","5")  // 肯定元素的值类型
val mutableList3 = mutableListOf(arr)                          // 可传入一个数组
val mutableList : ArrayList<String>  // 这里的ArrayList<>和Java里面的ArrayList一致

mutableList1.add("6")  // 添加元素
mutableList1.add("7")
mutableList1.remove(1)   // 删除某一元素

// 遍历
for(value in mutableList1){
    print("$value \t")
}

mutableList1.clear()   // 清空集合

输出结果为:

2   3   4   5   6   7

2.二、Set类型

Set类型集合的使用和List类型集合大体相同。这里不作详细的介绍,只讲解它和List类型集合不一样的地方。

  • 声明并初始化Set 的集合:使用 setOf(..)函数
  • 声明并初始化MutableSet 的集合:使用 mutableSetOf(..)函数

例1: 声明并初始化

val set1 = setOf(1,2,"3","4","2",1,2,3,4,5)
val mutableSet1 = mutableSetOf(1,2,"3","4","2",1,2,3,4,5)
val mutableSet2 : HashSet<String>  // 这里的HashSet<>和Java里面的HashSet<>一致

例2 :遍历集合,看效果与预计的有什么不一样

// 遍历
for(value in set1){
    print("$value \t")
}

输出结果:

1   2   3   4   2   3   4   5

在咱们预计的效果中,遍历的结果应该为:1 2 3 4 2 1 2 3 4 5,可是结果却少了一个1 2。那么咱们能够看出,Set类型集合会把重复的元素去除掉。这一点和Java是不谋而合的。这个特性也是Set类型集合与List集合类型的区别所在。

2.三、Map类型

Map<K,V>类型集合和List以及Set都有着差异。下面咱们看Map类型集合的声明及初始化。

同前面两种类型同样,Map一样也分为不可变与可变集合。其中:

  • 不可变的Map类型集合的初始化使用:mapOf()函数
  • 可变的Map类型集合的初始化使用:mutableMapOf()函数

不过初始化和前面两种类型有差异,Map集合类型是一种以键-值对的方式出现。例:

// 以键值对的形式出现,键与值之间使用to
val map1 = mapOf("key1" to 2 , "key2" to 3)
val map2 = mapOf<Int,String>(1 to "value1" , 2 to "value2")
val mutableMap = mutableMapOf("key1" to 2 , "key1" to 3)
val hashMap = hashMapOf("key1" to 2 , "key1" to 3)   // 同Java中的HashMap

map2.forEach{
    key,value -> println("$key \t $value")
}

输出结果为:

1    value1
2    value2

注意:当咱们的键存在重复时,集合会过滤掉以前重复的元素

例:

val map = val map1 = mapOf("key1" to 2 , "key1" to 3 , "key1" to "value1" , "key2" to "value2")

map.forEach{
    key,value -> println("$key \t $value")
}

输出结果为:

key1     value1
key2     value2

从上面的例子能够看出,当key值为key1时,元素只保留了最后一个元素。而过滤掉了以前key值相同的全部元素。

3、 集合类型的协变

试想一下,当一个集合赋值给另一个集合时,这里以List<E>举例,若是两个集合的类型也就是E类型相同时,赋值是没有问题的。若是类型不一样的状况,当E继承自M时。你就能够把List<E>赋值给List<M>了。这种状况称之为协变

我这里举两个例子

例1:

open class Person(val name : String , val age : Int){
    override fun toString(): String {
        return "Person(name='$name', age=$age)"
    }
}

class Student(name: String, age : Int, cls : String) : Person(name, age)

// 注意:Any是kotlin中的超类,故而Student类也是继承自Any的。这里你能够换成Person类结果是相同的
var listPerson: List<Any>
val listStudent : List<Student> = listOf(Student("张三",12,"一班"),Student("王五",20,"二班"))
listPerson = listStudent

listPerson.forEach { println(it.toString()) }

输出结果:

Person(name='张三', age=12)
Person(name='王五', age=20)

例2:当集合的类型相同或有继承关系时,一个集合使用MutableList,一个集合使用List的状况。

var mutableListPerson: MutableList<Person>
val mutableListStudent : List<Student> = listOf(Student("张三",12,"一班"),Student("王五",20,"二班"))
mutableListPerson = mutableListStudent.toMutableList()
mutableListPerson.add(Person("a",15))
mutableListPerson.add(Person("b",45))

mutableListPerson.forEach { println(it.toString()) }

输出结果为:

Person(name='张三', age=12)
Person(name='王五', age=20)
Person(name='a', age=15)
Person(name='b', age=45)

看上面的实例2,使用了一个toMutableList()函数,其实这个函数的意思是把List转换成了MutableList。在如下的源码中咱们能够看出:实际上是实例化了一个ArrayList

public fun <T> Collection<T>.toMutableList(): MutableList<T> {
    return ArrayList(this)
}

public fun <T> Iterable<T>.toMutableList(): MutableList<T> {
    if (this is Collection<T>)
        return this.toMutableList()
    return toCollection(ArrayList<T>())
}

SetMap集合的协变和上面的代码都相差很少,调用不一样的转换函数罢了。除了toMutableList()函数之外,还有着toList()toHashSet()toSet()等等函数。这些函数都是在Iterable接口的拓展函数。你们有兴趣能够本身去看看源码,这里不作详细的累述。

4、一些经常使用的处理集合类型的拓展函数

除了上面讲到的toList()toSet()toHastSet()toMutableList()toSet()toIntArray()等等拓展函数以外。还有一些经常使用的拓展的高阶函数。这里列举几个说明。并实例分析他们的做用。全部的源码都在kotlin\collections\_Collections.kt文件。

不过这里因为文章篇幅的缘由:这一节的内容会在下一章文章讲解。

请参见Kotlin——高级篇(五):集合之经常使用操做符汇总

总结

在这篇文章中,详细的讲解到了集合的几种类型的声明与使用,而且也对数组类型Array<T>温故了一遍。其实这篇文章的内容并非不少,你们主要记住集合类型初始化的几个标准函数,以及集合的类型协变。在下一篇文章中会对处理集合与数组的常见函数作出一个讲解以及源码的剖析。

源代码

若是各位大佬看了以后感受还阔以,就请各位大佬随便star一下,您的关注是我最大的动力。
个人我的博客Jetictors
GithubJteictors
掘金Jteictors

欢迎各位大佬进群共同研究、探索

QQ群号:497071402

相关文章
相关标签/搜索