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

时间:2022-09-07 11:49:03

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

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

目录

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

一、数组类型

Kotlin数组类型不是集合中的一种,但是它又和集合有着太多相似的地方。并且数组和集合可以互换。并且在初始化集合的时候也可以传入一个数组。用于数组类型在前面的章节已经讲解过了,这里就不在多做累述。有兴趣的朋友可以去看我前面关于数据类型的文章。

Kotlin——初级篇(三):数据类型详解

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

  • 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 :反转元素

val arr = arrayOf("1",2,3,4)
arr.reverse() // 文章后面会讲解forEach高阶函数。比for循环简洁多了
for (index in arr){
print("$index \t")
}

输出结果:

4   3   2   1

二、集合类型

  • 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文件

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

2.1、List类型

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

  • 声明并初始化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.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.3、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值相同的所有元素。

三、 集合类型的协变

试想一下,当一个集合赋值给另外一个集合时,这里以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接口的拓展函数。大家有兴趣可以自己去看看源码,这里不做详细的累述。

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

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

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

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

总结

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

源代码

如果各位大佬看了之后感觉还阔以,就请各位大佬随便star一下,您的关注是我最大的动力。

我的个人博客Jetictors

GithubJteictors

掘金Jteictors

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

QQ群号:497071402

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

Kotlin——高级篇(四):集合(Array、List、Set、Map)基础的更多相关文章

  1. Kotlin——高级篇(五):集合之常用操作符汇总

    在上一篇文章Kotlin--高级篇(四):集合(Array.List.Set.Map)基础中讲解到了数组Array<T>.集合(List.Set.Map)的定义与初始化.但是由于篇幅的原因 ...

  2. Kotlin——高级篇(二):高阶函数详解与标准的高阶函数使用

    在上面一个章节中,详细的讲解了Kotlin中关于Lambda表达式的语法以及运用,如果还您对其还不甚理解,请参见Kotlin--高级篇(一):Lambda表达式详解.在这篇文章中,多次提到了Kotli ...

  3. JAVA高级篇&lpar;四、JVM垃圾回收和调优&rpar;

    本文转自https://zhuanlan.zhihu.com/p/25539690 JVM GC(垃圾回收机制) 在学习Java GC 之前,我们需要记住一个单词:stop-the-world .它会 ...

  4. java架构《并发线程高级篇四》

    本章主要讲并发线程的常见的两种锁.重入锁和读写锁 一:重入锁(ReentrantLock) 概念:重入锁,在需要进行同步的代码加锁,但最后一定不要忘记释放锁,否则会造成锁永远不能释放,其他线程进不了 ...

  5. Kotlin——从无到有系列之高级篇(一):Lambda表达式

    如果您对Kotlin很有兴趣,或者很想学好这门语言,可以关注我的掘金,或者进入我的QQ群大家一起学习.进步. 欢迎各位大佬进群共同研究.探索 QQ群号:497071402 进入正题 经过前面一系列对K ...

  6. Kotlin——中级篇(二): 属性与字段详解

    在前面的章节中,详细的为大家讲解到了Kotlin中对类的类的定义.使用.初始化.初始化.类继承等内容,但是在一个类中,几乎上是不可能不出现属性与字段(field)的,这一篇文章就为大家奉上Kotlin ...

  7. 39&period;oracle高级篇

    标题说是高级篇,其实也就是相对于基础篇来说的,也不是很深奥,自己平时工作中也都会用到,这里回忆的并不是特别冷门的知识,不要掉以轻心,以为“高级”就觉得工作中不会用到了. 一.select into 和 ...

  8. C&num;高级知识点&amp&semi;&lpar;ABP框架理论学习高级篇&rpar;——白金版

    前言摘要 很早以前就有要写ABP高级系列教程的计划了,但是迟迟到现在这个高级理论系列才和大家见面.其实这篇博客很早就着手写了,只是楼主一直写写停停.看看下图,就知道这篇博客的生产日期了,谁知它的出厂日 ...

  9. Kotlin——初级篇(四):控制语句详解

    在前面 的章节中讲解了Kotlin语言中的数据类型.变量与常量的定义.不了解请参见前面的内容: Kotlin--初级篇(三):数据类型详解. Kotlin--初级篇(二)常量.变量.注释. 下面详细为 ...

随机推荐

  1. CFD冲蚀模拟的一些理论

    [TOC] 在CFD中计算颗粒对固体壁面的冲蚀往往采用冲蚀模型(Erosion Model). 1 冲蚀速率(Erosion Rate) 冲蚀速率定义为壁面材料在单位时间单位面积上损失的质量(单位:\ ...

  2. web开发学习之Http协议

    web入门 请求: request 浏览器向服务器发信息 响应:response 服务器回复浏览器 一个请求发出,一定有且仅有一个响应   http协议:对浏览器客户端余服务器的数据传输规范   ht ...

  3. 【python】编码

    来源:廖雪峰 看到一篇很不错的讲python编码的文章,转过来 划重点: unicode是一种统一的编码方式,它将所有的编码方式都统一到了同一套规范中,避免了乱码问题. encode() 表示从 un ...

  4. 201521123098 《Java程序设计》第7周学习总结

    1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 该方法调用了ind ...

  5. 老男孩Python全栈开发(92天全)视频教程 自学笔记06

    day6课程内容: tuple(元祖) 创建元祖: tup0=() #没有元素的一个元祖 tup1=(20,)#只有一个元素的元祖 元祖可读,不可修改 Dictionary(字典)#Python里唯一 ...

  6. 洛谷P3144 &lbrack;USACO16OPEN&rsqb;关闭农场Closing the Farm&lowbar;Silver

    题目描述 Farmer John and his cows are planning to leave town for a long vacation, and so FJ wants to tem ...

  7. &lbrack;Swift实际操作&rsqb;八、实用进阶-&lpar;5&rpar;通过间接代理进行对象间的消息传递

    本文将为你演示,如何通过简介代理的方式,进行对象间的消息传递在左侧的项目导航区,打开自定义视图的代码文件(CustomView.swift). import UIKit class CustomVie ...

  8. python 闭包&commat;装饰器

    1.装饰器 装饰器(Decorator)相对简单,咱们先介绍它:“装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”,听起来有点绕,没关系,直 ...

  9. Atitit&period;wrmi&&num;160&semi;web&&num;160&semi;rmi框架新特性

    Atitit.wrmi web rmi框架新特性 1. V1d  新特性1 1.1. 增加了精确参数1 1.2. 增加了req参数,命名参数模式..1 1.3. 增加了globale  传递隐含参数r ...

  10. 非常实用的JavaScript小技巧

    使用!!操作符转换布尔值 有时候我们需要对一个变量查检其是否存在或者检查值是否有一个有效值,如果存在就返回true值.为了做这样的验证,我们可以使用!!操作符来实现是非常的方便与简单.对于变量可以使用 ...