Kotlin——高级篇(四):集合(Array、List、Set、Map)基础
在实际的项目开发中,集合的运用可以说是多不胜数。不过Kotlin
中的集合运用和Java
中还是有很大的差别,他们两者之间,除了集合的类型相同以外,还包含集合的初始化的不同,以及Kotlin
对于集合封装特别多的高阶函数以供我们能更简单、更快捷的编写代码。不过在讲解集合之前,我先会对Kotlin
中的数组类型
做出一个讲解,大家可以当做是对数组Array<T>
的一个温故。
目录
一、数组类型
在
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
中,集合类型包含三种类型:它们分别是:List
、Set
、Map
,这三种类型都有几个共通点:
- 它们都是接口,并不是实际的类。
- 它们都继承至
Collection<out E>
接口,而Collection<out E>
又继承与Iterable<out T>
接口。它们几乎上只实现了isEmpty()、size属性、get()、contains()
等方法。这一点和Java
类似。- 这三种集合类型分别有存在
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中的HashMapmap2.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 = listStudentlistPerson.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>())
}
Set
、Map
集合的协变和上面的代码都相差不多,调用不同的转换函数罢了。除了toMutableList()
函数以外,还有着toList()
、toHashSet()
、toSet()
等等函数。这些函数都是在Iterable
接口的拓展函数。大家有兴趣可以自己去看看源码,这里不做详细的累述。
四、一些常用的处理集合类型的拓展函数
除了上面讲到的toList()
、toSet()
、toHastSet()
、toMutableList()
、toSet()
、toIntArray()
等等拓展函数之外。还有一些常用的拓展的高阶函数。这里列举几个说明。并实例分析他们的作用。所有的源码都在kotlin\collections\_Collections.kt
文件。
不过这里由于文章篇幅的原因:这一节的内容会在下一章文章讲解。
请参见Kotlin——高级篇(五):集合之常用操作符汇总
总结
在这篇文章中,详细的讲解到了集合的几种类型的声明与使用,并且也对数组类型Array<T>
温故了一遍。其实这篇文章的内容并不是很多,大家主要记住集合类型初始化的几个标准函数,以及集合的类型协变。在下一篇文章中会对处理集合与数组的常见函数做出一个讲解以及源码的剖析。
源代码
如果各位大佬看了之后感觉还阔以,就请各位大佬随便star
一下,您的关注是我最大的动力。
我的个人博客:Jetictors
Github:Jteictors
掘金:Jteictors
欢迎各位大佬进群共同研究、探索
QQ群号:497071402
转载于:https://www.cnblogs.com/Jetictors/p/9237108.html
Kotlin——高级篇(四):集合(Array、List、Set、Map)基础相关推荐
- 老的消息中间件投递失败的类型值_RabbitMQ消息中间件技术精讲11 高级篇四 confirm 确认消息...
RabbitMQ消息中间件技术精讲11 高级篇四 confirm 确认消息 理解Confirm消息确认机制: 消息的确认,是指生产者投递消息后,如果broker收到消息,则会给生产者一个应答: 生产者 ...
- c#扩展方法奇思妙用高级篇四:对扩展进行分组管理
从系列文章开篇到现在,已经实现的很多扩展了,但过多的扩展会给我们带来很多麻烦,试看下图: 面对这么多"泛滥"的扩展,很多人都会感到很别扭,的确有种"喧宾夺主"的 ...
- DirectX12(D3D12)基础教程(外篇四)——用Assimp载入模型基础操作(无渲染纯命令行版)
目录 1.前言 2.Assimp使用简介 3.Assimp头文件和库文件引入 4.Import模型文件 5.aiScene基本数据结构及遍历 5.1.Assimp类图及关系 5.2.aiScene遍历 ...
- Kotlin——中级篇(二): 属性与字段详解
在前面的章节中,详细的为大家讲解到了Kotlin中对类的类的定义.使用.初始化.初始化.类继承等内容,但是在一个类中,几乎上是不可能不出现属性与字段(field)的,这一篇文章就为大家奉上Kotlin ...
- Docker入门(基础篇+高级篇)
Docker 参考手册基础篇+高级篇 一.Docker常用命令 docker run docker stop docker start 进入一个运行中的容器 docker ps docker imag ...
- kotlin 添加第一个 集合_Flutter开发必学Dart语法篇之集合操作符函数与源码分析...
简述: 在上一篇文章中,我们全面地分析了常用集合的使用以及集合部分源码的分析.那么这一节讲点更实用的内容,绝对可以提高你的Flutter开发效率的函数,那就是集合中常用的操作符函数.这次说的内容的比较 ...
- 【建议收藏】2020年中高级Android大厂面试秘籍,为你保驾护航金三银四,直通大厂(Android高级篇下)...
前言 成为一名优秀的Android开发,需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样~. A awesome android expert interview questions a ...
- 黑马JavaScript笔记(四)高级篇
JavaScript面向对象编程 01 面向对象编程介绍 1.1 两大编程思想 面向过程 面向对象 1.2 面向过程编程 POP(Process-oriented programming) 面向过程, ...
- 【建议收藏】2020年中高级Android大厂面试秘籍,为你保驾护航金三银四,直通大厂(Android基础篇)...
前言 成为一名优秀的Android开发,需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样~. A awesome android expert interview questions a ...
- 【建议收藏】2020年中高级Android大厂面试秘籍,为你保驾护航金三银四,直通大厂(Android高级篇-2)...
前言 成为一名优秀的Android开发,需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样~. A awesome android expert interview questions a ...
最新文章
- 在ASP.NET MVC中进行排序
- hdu4530 水题
- python填充空值_Python机器学习(九十一)Pandas 填充(Imputation)空值
- html5 居中 字体 字号,css字体水平居中
- canvas的getImageData和putImageDataAPI
- 事务的隔离级别(Transaction isolation levels)5
- c++ linux 线程等待与唤醒_Linux驱动程序基石-POLL机制(附.视频)
- linux php mysql安装包下载_在linux下手动安装 apache, php, mysql--终极版
- 关于HTML+CSS3的一些笔记
- 关于datawindow does not have update capability
- 蓝桥杯C++深度优先搜索(dfs)之组队,迷宫,走方格
- 股票控件android,一个Android股票应用(含源码)
- 单片机C语言中关键词code的作用
- 计算机四级网络工程师
- TSINGSEE青犀视频平台人脸识别比对控制比对时间间隔的代码设计
- 十个英语口语学习网站
- 双通道中频信号数字下变频及相位差估计(FPGA)
- python语言编程中的感叹号_python 感叹号的作用
- sap文档服务器,SAP程序文档管理方案
- 按关键字爬取网页信息
热门文章
- nacos心跳机制重复发送原理
- mysql中count(*)、count(1)和count(字段)的区别
- )C# Enum,Int,String的互相转换 枚举转换
- Linux---Samba文件共享服务
- Grails 技巧 - View 篇
- string与StringBuilder 性能差距到底有多大
- 关于typedef的使用
- PLSQL常用方法汇总
- nodejs后台系列--第四篇--koa
- 如何运行python代码将各个表格的信息集合在一起_如何利用Python编程批量处理Excel来提高日常工作效率!...