Kotlin快速入门系列11

Kotlin的集合

集合类

Java类库有一套相当完整的容器集合类用来持有对象。跟Java一样,集合类存放的都是对象的引用,而非对象本身(我们经常说的集合指的是集合中对象的引用),Kotlin的集合类是在Java的集合类库基础上进行的优化,新引入了不可变集合类等扩展,相关类和API都在kotlin.collections包里

Kotlin的集合根据本身可变性可以分为两种可变集合类不可变集合类

常用的集合类主要有三种

·List(列表):List中的元素以线性方式存储,可以存放重复对象且列表中的元素是有序地排列。根据可变性分为只读不可变的List和可变MutableList(可写入、删除数据)。

·Set():存放的元素无序、不重复根据可变性分为不可变Set和可变MutableSet(可写入、删除数据)。

·Map(映射):持有的对象是“键值对”形式,每一个对象都包含一对键值Key-Value对象。其中key是唯一的,key决定对象在映射中的存储位置(但key本身并不能决定对象的存储位置,它通过哈希算法产生一个被称做哈希值的整数值,这个哈希值对应value的存储位置)。Map与List、Set一样,Map也分为只读Map和可变 MutableMap(可写入、删除数据)。需要注意的是,Map没有继承于Collection接口。

从数据结构的角度来看,List中的下标类似键值对中的Key, 只不过Key是有序的Int类型,所以说List也可以说是一种特殊的Map数据结构。而Set也是Key为Int类型,但是Value值是不能重复的特殊Map。

集合类接口

Kotlin中集合类接口的结构层次如图所示

各接口对应功能如下:

集合的创建

常用API:

· 可使用listOf()、setOf()、mapOf()函数创建不可变的List 容器、Set容器、Map容器。

· 可使用mutableListOf()、 mutableSetOf()、mutableMapOf()函数来创建可变的MutableList容器、MutableSet容器、MutableMap容器。

· 可使用emptyList<>()创建一个空的List对象,使用emptySet()创建一个空的只读Set,使用emptyMap<K,V>()创建一个空的Map。

· Map还有相关linkedHashMapOf()和haspMapOf()。常用的mapOf()和mutableMapOf()创建的对象性质类似Java的LinkedHashMap。

声明格式代码示例如下:

val list = listOf(1,2,3,4,5)                        //不可变List
val mutableList = mutableListOf("1","2","3")            //可变MutableListval set = setOf(1,2,3,4,5)                          //不可变Set
val mutableSet = mutableSetOf("1","2","3")          //可变MutableSetval map = mapOf(1 to "one",2 to "two",3 to "haha")                          //创建不可变Map
val mutableMap = mutableMapOf(1 to "one",2 to "two",3 to "haha")            //创建可变MutableMap

要想创建没有元素的空List,使用listOf()即可。不过创建空变量时,变量的类型不能省略(泛型),需要在声明时显式声明:

val emptyList: List<Int> = listOf() //显式声明List中的元素类型为Int
val emptyLIst2 = emptyList<Int>()val emptySet: Set<Int> = setOf() //显式声明Set中的元素类型为Int
val emptySet2 = emptySet<Int>()val emptyMap: Map<String,String> = mapOf() //显式声明Map中的元素类型为String,String键值对
val emptyMap2 = emptyMap<String,String>()

可以得出只读集合(listOf、setOf 和 mapOf)与可变集合(mutableList、mutableSetOf和 mutableMapOf)对应的kotlin&java集合的关系表:

方法

Java类型

listOf()

kotlin.collections.EmptyList

setOf()

kotlin.collections.EmptySet

mapOf()

kotlin.collections.EmptyMap

listOf(element: T)

java.util.Collections$SingletonList

setOf(element: T)

java.util.Collections$SingletonSet

mapOf(pair: Pair<K, V>)

java.util.Collections$SingletonMap

listOf(vararg elements: T)

java.util.Arrays$ArrayList

setOf(vararg elements: T)

java.util.LinkedHashSet

mapOf(vararg pairs: Pair<K, V>)

java.util.LinkedHashMap

mutableList()

java.util.ArrayList

mutableSetOf()

java.util.LinkedHashSet

mutableMapOf()

java.util.LinkedHashMap

元素遍历

List、Set类继承了Iterable接口,里面扩展了forEach函数来进行遍历元素操作;Map接口中也扩展了forEach函数来迭代遍历元素。示例如下:

fun main(args: Array<String>) {var list: List<Int> = listOf(1,2,3)list.forEach{print(it)          //打印123 ,set和map使用同理}}

如果我们想在迭代遍历元素的时候访问index下标,在List和Set中可以使用forEachIndexed函数。如下示例:

fun main(args: Array<String>) {var list: List<String> = listOf("a","b","c")list.forEachIndexed { index: Int, i: String ->       //第1个参数是下标,第2个参数是list中元素类型println(" list key is $index and value is $i")}
}

对应看到的控制台输出为:

映射函数

即对集合中每一个元素应用给定的函数,并把结果收集到一个新集合。基本的映射函数是 map()。 它将给定的 lambda 函数应用于每个后续元素,并返回 lambda 结果列表。 结果的顺序与元素的原始顺序相同。如果还需要用到元素索引作为参数的转换,请使用 mapIndexed()(对比下上面的forEachIndexed(),有没有发现什么?)。示例如下:

fun main(args: Array<String>) {val number = setOf(1, 2, 3)println(number.map { it * 3 })                  //对应输出 [3, 6, 9]println(number.mapIndexed {     keys, value -> value * keys })  //对应输出[0, 2, 6]
}

如果转换的结果在某些元素上产生空值,则可以通过调用 mapNotNull() 函数取代 map() 或 mapIndexedNotNull() 取代 mapIndexed() 来从结果集中过滤掉 null 值。示例如下:

fun main(args: Array<String>) {val number = setOf(1, 2, 3, 4)println(number.map { if (it == 3) null else it * 2})println(number.mapNotNull { if (it == 3) null else it * 2})println(number.mapIndexed { keys, value -> if (keys == 2) null else value * keys })println(number.mapIndexedNotNull { keys, value -> if (keys == 2) null else value * keys })
}

对应的控制台结果为:

观察其源码,可以发现:

/*** Returns a list containing the results of applying the given [transform] function* to each element in the original collection.* * @sample samples.collections.Collections.Transformations.map*/
public inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {return mapTo(ArrayList<R>(collectionSizeOrDefault(10)), transform)
}
/*** Applies the given [transform] function to each element of the original collection* and appends the results to the given [destination].*/
public inline fun <T, R, C : MutableCollection<in R>> Iterable<T>.mapTo(destination: C, transform: (T) -> R): C {for (item in this)destination.add(transform(item))return destination
}

这个过程,就是创建一个新的ArrayList集合,遍历原集合,将函数类型对象处理过的值添加到新ArrayList对象中,并返回新的ArrayList对象。

此外,映射转换时,有两个选择:转换键,使值保持不变,反之亦然。 要将指定转换应用于键,请使用 mapKeys();反过来,mapValues() 转换值。 这两个函数都使用将映射条目作为参数的转换,因此可以操作其键与值。示例如下:

fun main(args: Array<String>) {val number= mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 4)println(number.mapKeys { it.key })println(number.mapValues { it.value + it.key.length })
}

对应控制台输出为:

此外kotlin还有一个flatten()函数,用法在理解上是跟map()相反的场景,使用场景较少,这里不做重复介绍了。

过滤函数

filter()是kotlin最常用的高阶函数之一,作用就是过滤。它可以对Collection集合、Map集合或数组元素进行过滤,Collection集合和数组返回的是一个List集合,Map集合返回的还是一个Map集合。

fun main(args: Array<String>) {val numbers = listOf("one", "two", "three", "four")val newNumbers = numbers.filter { it.length > 3 }println(newNumbers)val numbersMap = mapOf("key10" to 1, "key2" to 2, "key30" to 3, "key4" to 4)val newMaps = numbersMap.filter { (key, value) -> key.endsWith("0") && value > 2}println(newMaps)
}

对应的控制台输出为:

与上述的map()类似,filter也有filterIndexed()(返回索引和值)和filterNot()(过滤空对象):

fun main(args: Array<String>) {val numbers = listOf("one", "two", "three", "four")val newNumbersOne = numbers.filter { it.length <= 3 }val newNumbersTwo = numbers.filterIndexed { index, s -> (index != 0) && (s.length < 5) }val newNumbersThree = numbers.filterNot { it.length <= 3 }println(newNumbersOne)println(newNumbersTwo)println(newNumbersThree)
}

对应输出结果为:

我为什么说这个使用场景较多呢,假设你现在有几个Bean对象,要拿Bean对象的某一个属性进行对比(不一定是比大小),然后获取对比后的数据,就可以用到fliter()(这个场景在实际开发过程中很常见)。例如如下示例:

data class Students (val id: Int,var name:String,var age:Int,var score:Int)fun main(args: Array<String>) {var studentList = listOf(Students(1,"jack",18,88),Students(2,"nick",19,86),Students(3,"James",20,99))val student = studentList.filter { it.age > 18 }   //过滤出studentList中年龄大于18的println(student)
}

对应控制台输出为:

排序函数

Kotlin集合类中提供了倒序排列集合元素的函数reversed(),具体使用与Java的reversed()一样。示例如下:

fun main(args: Array<String>) {val list = listOf(1,2,3,4,5)val set = setOf("abc","jkl","zvm")list.reversed()set.reversed()println(list)           //对应输出[1, 2, 3, 4, 5]println(set)            //对应输出[abc, jkl, zvm]
}

对应的升序排序函数是sorted(),使用方法也跟Java一样,不做赘述:

fun main(args: Array<String>) {val list = listOf(9,2,4,6,1)val set = setOf(5,3,6)println(list.sorted())           //对应输出[1, 2, 4, 6, 9]println(set.sorted())            //对应输出[3, 5, 6]
}

元素去重

distinct()函数,功能描述即去除集合内的重复性元素。list和set可以使用,map不行(这个可以猜到的吧)。示例如下:

fun main(args: Array<String>) {val list = listOf(9,2,9,4,1,1,4,6,1)val set = setOf(5,3,5,6,1,6)println(list.distinct())           //对应输出[9, 2, 4, 1, 6]println(set.distinct())            //对应输出[5, 3, 6, 1]
}

使用方式简单,这里不做赘述。

End,如有其他问题请留言。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/443632.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zookeeper分布式队列实战

目录 Zookeeper分布式队列 普通方式实现 设计思路 具体实现 使用Curator实现 具体实现 注意事项 Zookeeper分布式队列 常见的消息队列有:RabbitMQ&#xff0c;RocketMQ&#xff0c;Kafka等。Zookeeper作为一个分布式的小文件管理系统&#xff0c;同样能实现简单的队列功…

科技云报道:云原生PaaS,如何让金融业数字化开出“繁花”?

科技云报道原创。 在中国金融业数字化转型的历史长卷中&#xff0c;过去十年无疑是一部磅礴的史诗。 2017年&#xff0c;南京银行第一次将传统线下金融业务搬到了线上。那一年&#xff0c;它的互联网金融信贷业务实现了过去10年的业务总额。 2021年&#xff0c;富滇银行通过…

Unity 自动轮播、滑动轮播

如图所示&#xff0c;可设置轮播间隔&#xff0c;可左右滑动进行轮播 1.在UGUI创建个Image&#xff0c;添加自动水平组件 2.添加并配置脚本 3.代码如下&#xff0c;都有注释 using UnityEngine; using UnityEngine.UI;public class IndicatorManager : MonoBehaviour {public …

远程连接服务器:Ping通但SSH连接失败的解决办法

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言常见问题影响SSH的因素本地影响因素防火墙设置网络配置文件 远程主机影响因素放行…

vulnhub靶场之Matrix-Breakout 2 Morpheus

一.环境搭建 1.靶场描述 This is the second in the Matrix-Breakout series, subtitled Morpheus:1. It’s themed as a throwback to the first Matrix movie. You play Trinity, trying to investigate a computer on the Nebuchadnezzar that Cypher has locked everyone…

力扣hot100 前 K 个高频元素 小根堆 流 IntStream

Problem: 347. 前 K 个高频元素 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考 小根堆&#xff08;维护k个高频元素&#xff09;遍历所有元素&#xff0c;当前堆大小 < k 或者 当前元素出现次数大于堆顶元素出现次数&#xff1a;替换掉堆顶元素 复杂…

细谈Java的String类

目录 1. 创建对象的思考 2. 字符串常量池&#xff08;StringTable&#xff09; 3. intern方法 1. 创建对象的思考 下面两种创建String对象的方式相同吗&#xff1f; public static void main(String[] args) {String s1 "hello";String s2 "hello";St…

迁移学习实现图片分类任务

导入工具包 import time import osimport numpy as np from tqdm import tqdmimport torch import torchvision import torch.nn as nn import torch.nn.functional as Fimport matplotlib.pyplot as plt %matplotlib inline# 忽略烦人的红色提示 import warnings warnings.fi…

【实战】使用Helm在K8S集群安装MySQL主从

文章目录 前言技术积累什么是HelmStorageClass使用的工具版本 helm 安装 MySQL 1主2从1. 添加 bitnami 的仓库2. 查询 MySQL 资源3. 拉取 MySQL chart 到本地4. 对chart 本地 values-test.yaml 修改5. 对本地 templates 模板 修改6. 安装 MySQL 集群7. 查看部署的 MySQL 集群8.…

11.Ubuntu

目录 1. 什么是Ubuntu 1.1. 概述 1.2. Ubuntu版本简介 1.2.1. 桌面版 1.2.2. 服务器版 2. 部署系统 2.1. 新建虚拟机 2.2. 安装系统 2.3. 部署后的设置 2.3.1. 设置root密码 2.3.2. 关闭防火墙 2.3.3. 启用允许root进行ssh 2.3.4. 安装所需软件 2.3.5. 制作快照 …

经典左旋,指针面试题

今天给大家带来几道面试题&#xff01; 实现一个函数&#xff0c;可以左旋字符串中的k个字符。 例如&#xff1a; ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 我们可以先自己自行思考&#xff0c;下面是参考答案&#xff1a; 方法一&#xff1a; #define _CRT_SEC…

linux 使用命令创建mysql账户

目录 前言创建步骤 前言 mysql默认有一个root用户&#xff0c;这个账户权限太大了&#xff0c;用起来不太安全&#xff0c;我们通常是重新那家一个账户用于一般的数据库操作&#xff0c;下面介绍如何通过命令创建一个mysql账户。 创建步骤 登录mysql mysql -u root -p输入roo…