Kotlin学习之集合

原文链接 Kotlin Collections

现代的软件一般比较复杂,程序语言中的基本数据类型往往不能满足需要,除了基本的数据类型以外,还有对象的容器也非常的重要,比如线性容器(数组,列表和Set)和二维容器(哈希表)等。今天就来学习一下Kotlin中的容器。

Kotlin Collections

集合就是用于处理一组对象的容器,因为用的人较多,所以就成了标准库。常见的集合有三种主要类型,列表类,Set类和Map类。

线性容器

这里并不单纯指类List,主要的意思是线性的容器,它的特点是以相对顺序存储同一类型的对象,有一个整数索引(index)来表示其相对的位置,查找性能差,其他还好。代表为数组。

数组

最简单也是使用最为广泛的线性容器,不用过多的介绍了,可以参考之前的文章。

最大的弊端就是长度是固定的,长度在创建数组时就确定了,后面就改不了了。所以,必须在事先要能够确定数组的长度

创建复杂数组

比如数组的元素是一个Collection,而非常见的基本数据类型,这时要如何写?

       val carray = arrayOf<MutableList<Int>>(mutableListOf(),mutableListOf())val narray = Array<MutableList<Int>>(10) { mutableListOf() }

关键就在于要声明元素的类型,其他的与基本数据类型的数组是一样的。另外,如果数组数量比较少,方便直接写,那就用字面构造函数,其实很方便。或者用数组元素的构造方法也可以。

多维数组

以最为常见的二维数组来说,要如何创建?

       val smatrix = arrayOf(arrayOf(1, 2, 3),arrayOf(4, 5, 6),arrayOf(7, 8, 9))val matrix = Array(5) { IntArray(6) }

Ranges

用于表示区间的表达式,最为直观理解就是数组的索引,用操作符…来表示区间,比如0~9,就是0…9,通常用于for-loop中:

if (i in 1..4) { // equivalent of i >= 1 && i <= 4print(i)
}for (i in 1..4) print(i) // for (int i = 1; i <= 4; i++) print(i)

还可以指定步长和边界,以及方向:

for (i in 0 until 10) { // for (int i = 0; i < 10; i++)print(ln)
}for (i in 0 until 10 step 2) { // for (int i = 0; i < 10; i += 2)print(ln)
}for (i in 9 downTo 0) { // for (int i = 9; i >= 0; i--)print(i)
}

还可以用于字符,比如:

for (c in 'a'..'z') { // for (char c = 'a'; c <= 'z'; c++)print(c)
}

Range是一个表达式,所以在其之上做其他操作,但需要注意这时需要加上括号,比如:

    for (i in (0..9).filter {it % 2 == 0 }) {println(i) // only evens}for (c in ('a'..'z').map { it.toUpperCase() }) {println(c) // upper case}

需要注意,虽然Ranges方便操作数组的索引,但如果想要带着索引遍历数组的话,还是要用专用的遍历方式,而不是用Range,比如:

for ((index, value) in array.withIndex()) {println("the element: [$index] = $value")
}
注意与repeat的区别

Ranges是一个数据结构代表着一个区间,这个区间可能是一个整数范围,也可能是一个字符范围,其实也可以是其他自定义数据类型,只要能表达 出区间的概念。只不过整数区间是为常用的一种方式,以及整数区间可以方便当作数组和列表的索引。

但有时如果仅仅想重复一件事情n次,那就没有必要用Ranges,虽然它也可以,这时最为方便的是函数repeat,它与区间的唯一区别是repeat是没有返回值的,它仅是把一件事情重复n次,但没有返回值也就是说没有办法再转化为其他数组或者列表。

repeat(10) { println("repeat # $it") }
//repeat # 0
//repeat # 1
//repeat # 2
//repeat # 3
//repeat # 4
//repeat # 5
//repeat # 6
//repeat # 7
//repeat # 8
//repeat # 9

而比如Ranges是可以转化为其他数组和列表的:

(0 until 5).map { it * it }.toIntArray()
// [0, 1, 4, 9, 16]

列表List

列表可以简单理解为无限长的数组,它最大的特点是长度不固定,不必事先定好长度,它会随着添加元素而自动增长。所以,当你事先不知道容器的长度时,就需要用List。它是一个泛型,其余操作与数组一样。

val names = listOf("James", "Donald", "Kevin", "George")
names.map { it.toUpper() }.forEach { println(it) }

序列Sequence

序列与列表比较难区分,直观上它们是一样的。简单来说它并不是容器,它并不持有对象,它生产对象,类似于物理上的信号发射器和RxJava中的Observable,是有时序上的概念的,当你需要时它就生产出来一个元素。

队列queue

队列可以用双端队列deque(读作dek),具体实现对象是ArrayDeque<T>。

双端队列是强大的数据结构,即可以用作队列,也可以用作栈。

Set容器

Set是一个不含有重复元素的容器,特点是不会保存相对顺序,可以快速实现检索

    val names = setOf("James", "Harden", "Donald", "Joe")for (nm in names) {println(nm)}names.filter { it.length > 4 }.forEach { println(it) }

Map容器

由映射键->值对组成的二维容器,键不可重复,值可以重复,不会保存相对顺序,也可以用于快速检索。

    val nameMap = mapOf("James" to 15, "Harden" to 30, "Donald" to 80, "Joe" to 86)for (nm in nameMap.keys) {println(nm)}for (age in nameMap.values) {println(age)}for (e in nameMap.entries) {println("${e.key} is ${e.value}")}nameMap.filter { it.key.length > 5 }.forEach { println("${it.key} = ${it.value}") }

注意Immutability

有一个地方需要特别注意,那就是容器的不可变性Immutability,用常规的方法创建的集合对象是不可变的Immutable,就是无法向其中添加元素也无法删除元素。对象的不可变Immutable在函数式编程中是很重要的特性可以有效的减少异步和并发带来的状态一致性问题

val names = listOf("James", "Donald", "Kevin", "George")
names.add("Paul") // compile error, names is immutable
names.map { it.toUpper() }.forEach { println(it) }

这样写会有编译错误,因为用listOf创建的列表对象是不可变的Immutable。如果想要改变就必须用支持更改的对象,如MutableList, MutableSet和MutableMap,如:

val names = mutableListOf("James", "Donald", "Kevin", "George")
names.add("Paul") // okay
names.map { it.toUpper() }.forEach { println(it) }

如果有可能还是要尽可能的用不可变对象(Immutable objects)

集合的操作

集合的操作就是函数式的三板斧过滤filter,转化map和折叠化约fold/reduce,前面讲的所有的容器都是支持的,结合lambdas可以写出非常规范的函数式代码。

参考资料

  • Kotlin Collections
  • Kotlin常用Collection集合操作整理
  • Kotlin Collections Guide
  • Kotlin Ranges

原创不易,打赏点赞在看收藏分享 总要有一个吧

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

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

相关文章

C语言:输出所有“水仙花数”。“水仙花数”是指一个3位数,其各位数字的立方和等于该数本身,如153=1^3 +5^3+3^3

分析&#xff1a; 在主函数 main 中&#xff0c;程序首先定义四个整型变量 m、a、b 和 c&#xff0c;并用于计算和判断水仙花数。然后使用 printf 函数输出提示信息。 接下来&#xff0c;程序使用 for 循环结构&#xff0c;从 100 到 999 遍历所有三位数。对于每个遍历到的数 m…

Mac电脑数据库管理 Navicat Premium 15中文 for mac

Navicat Premium 15是一款强大的数据库管理和开发工具。它支持多种数据库类型&#xff0c;包括MySQL、MariaDB、Oracle、PostgreSQL等&#xff0c;可以帮助用户方便地管理和维护数据库。该软件提供了直观的用户界面和强大的功能&#xff0c;可以帮助用户快速创建、编辑和删除数…

ubuntu/vscode下的c/c++开发之-CMake语法与练习

Cmake学习 1 语法特性介绍 基本语法格式&#xff1a;指令(参数 1 参数 2...) 参数使用括弧括起参数之间使用空格或分号分开 指令是大小写无关的&#xff0c;参数和变量是大小写相关的 set(HELLO hello.cpp) add_executable(hello main.cpp hello.cpp) ADD_EXECUTABLE(hello ma…

2023大模型安全解决方案白皮书

今天分享的是大模型系列深度研究报告&#xff1a;《2023大模型安全解决方案白皮书》。 &#xff08;报告出品方&#xff1a;百度安全&#xff09; 报告共计&#xff1a;60页 前言 在当今迅速发展的数字化时代&#xff0c;人工智能技术正引领着科技创新的浪潮而其中的大模型…

C语言:写一个函数,实现3*3矩阵的转置(指针)

分析&#xff1a; 在主函数 main 中&#xff0c;定义一个 3x3 的整型数组 a&#xff0c;并定义一个指向整型数组的指针 p。然后通过循环结构和 scanf 函数&#xff0c;从标准输入中读取用户输入的 3x3 矩阵的值&#xff0c;并存储到数组 a 中。 接下来&#xff0c;调用 mov…

Docker 的诅咒:曾以为它是终极解法,最后却是“罪大恶极”?

系统管理中的基础问题 打包软件一直是系统管理中的一大基础问题。它非常重要&#xff0c;对系统的使用方式有着巨大影响&#xff0c;甚至让包管理器成为区分操作系统的一项重要指标。 以 Windows 为例&#xff1a;在很多“Linux 派”眼中&#xff0c;这款操作系统最不讨喜的就…

docker 安装oracle 11,配置客户端远程连接

最近由于工作需要&#xff0c;oracle11数据库的导入导出&#xff0c;所以自己在电脑上模拟个数据库环境&#xff0c; 1.docker的安装&#xff0c;可以参考之前文档&#xff0c;也可以直接yum install 包名字安装 2.下载镜像 docker pull registry.cn-hangzhou.aliyuncs…

数据结构 | 堆排序

数据结构 | 堆排序 文章目录 数据结构 | 堆排序建立大堆排序结果以及全部代码 如果没有看过堆的实现的话可以先看前面的一章堆的实现&#xff0c;然后再来看这个堆排序&#xff0c;都是比较简单的~~ 这里堆排序首先建堆&#xff0c;建堆是要建小堆还是大堆呢&#xff1f; 在堆排…

案例029:基于微信小程序的阅读网站设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

鸿蒙应用开发-初见:ArkUI

编程范式&#xff1a;命令式->声明式 以一个卡片的实现做下讲解 命令式 简单讲就是需要开发用代码一步一步进行布局&#xff0c;这个过程需要开发全程参与。 Objective-C UIView *cardView [[UIView alloc] init]; cardView.backgroundColor [UIColor whiteColor]; ca…

Qt_一个由单例引发的崩溃

Qt_一个由单例引发的崩溃 文章目录 Qt_一个由单例引发的崩溃摘要关于 Q_GLOBAL_STATIC代码测试布局管理器源码分析Demo 验证关于布局管理器析构Qt 类声明周期探索更新代码获取父类分析Qt 单例宏源码 关键字&#xff1a; Qt、 Q_GLOBAL_STATIC、 单例、 UI、 崩溃 摘要 今…

R语言实操记录——R包无法安装,报错:Warning in system(cmd) : ‘make‘ not found

R语言 R语言实操记录——R包无法安装&#xff0c;报错&#xff1a;Warning in system(cmd) : ‘make‘ not found 文章目录 R语言一、起因二、具体步骤2.1、确认问题源2.2、安装RTools2.3、与R(/Rstudio)绑定2.4、验证可行性 三、疑惑 一、起因 R语言在包的安装上是真的方便&…

西北大学计算机844考研-23年计网计算题详细解析

西北大学计算机844考研-23年计网计算题详细解析 1.计算无传输差错状态下停止—等待ARQ协议效率,电磁波传播速率为2*10^8m/s&#xff0c;链路长为2000m&#xff0c;帧长度为1000比特&#xff0c;计算传输速率10kbps及10Mbps时的协议效率&#xff08;即信道利用率&#xff09; …

中低压MOSFET 2N7002KW 60V 300mA 双N通道 SOT-323封装

2N7002KW小电流双N通道MOSFET&#xff0c;电压60V电流300mA&#xff0c;采用SOT-323封装形式。超高密度电池设计&#xff0c;适用于极低的ros (on)&#xff0c;具有导通电阻和最大直流电流能力&#xff0c;ESD保护。可应用于笔记本中的电源管理&#xff0c;电池供电系统等产品应…

外观设计模式

package com.jmj.pattern.facade;public class Light {public void on(){System.out.println("打开电灯...");}public void off(){System.out.println("关闭电灯...");} }package com.jmj.pattern.facade;public class AirCondition {public void on(){S…

R语言阶段复习一

创建一个长度为7的字符向量&#xff0c;元素为"A", "B", "C", "D", "E", "F", "G"&#xff0c;并命名为vec1。 创建一个因子&#xff0c;包含6个水果&#xff1a;"apple", "banana"…

stack和queue

目录 1.什么是stack 2.容器适配器 3.stack的使用 top push pop 4.模拟实现stack 1.什么是stack 1. stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行 元素的插入与提取操作。(后进先出) 2. stack是作为容…

C语言:一个数如果恰好等于除它本身外的因子之和,这个数就称为完数。例如6=1+2+3。编程找出1000以内的所有完数。

分析&#xff1a; 在主函数 main 中&#xff0c;程序首先定义三个整型变量 m、s 和 i&#xff0c;并用于计算和判断完数。然后使用 printf 函数输出提示信息。 接下来&#xff0c;程序使用 for 循环结构&#xff0c;从 2 到 999 遍历所有的数。对于每个遍历到的数 m&#xff0c…

如何通过nginx进行反向代理

简单介绍 正向代理 正向代理服务器是一个位于客户端和原始服务器(origin server)之间的服务器&#xff0c;为了能够从原始服务器取得内容&#xff0c;客户端向代理发送一个请求并指定目标(原始服务器)&#xff0c;然后代理向原始服务器转交请求并将获得的内容返回给客户端。正向…

Ubuntu+Tesla V100环境配置

系统基本信息 nvidia-smi’ nvidia-smi 470.182.03 driver version:470.182.03 cuda version: 11.4 查看系统体系结构 uname -aUTC 2023 x86_64 x86_64 x86_64 GNU/Linux 下载miniconda https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/?CM&OA https://mi…