Kotlin集合与数组

可空性和集合

函数的参数可以为可空的,集合的类型参数也是可以声明为可空的. 下面来看一个创建一个包含可空值的集合

fun readNumbers(reader : BufferedReader) : List<Int?>{
    val result = ArrayList<Int?>()
    for(line in reader.lineSequence()){
        try{
            val number = line.toInt()
            result.add(number)
        }
        catch(e : NumberFormatException){
            result.add(null)
        }
    }
    return result
} 

List<Int?>可以持有Int或者null. 另外还要注意下面情况,列表中的单个值是可空的和整个列表是可空的.

另外还有一种情况是,你可能需要声明一个变量持有可空的列表,并且包含可空的数字。Kotlin中的写法是List<Int?>?, 有两个问号。这种情况下使用变量自己的值的时候,以及使用列表中每个元素的值的时候,都需要使用null检查.
下面一个例子展示使用可空值的集合

fun addValidNumbers(numbers : List<Int?>){
    var sumOfValidNumbers = 0
    var invalidNumbers = 0
    for(number in numbers){
        if (number != null){
            sumOfValidNumbers += number
        } else{
            invalidNumbers++
        }
    }
    printlin(“Sum of valid numbers : $sumOfValidNumbers”)
    printlin(“Invalid numbers : ” $invalidNumbers)
} 

在使用List中每一个元素之前必须对其进行判空.
遍历一个包含可空值的集合并过滤掉null是一个非常常见的操作,因此Kotlin提供了一个标准库函数filterNotNull来完成它. 这里可以用它来大大简化前面的例子.

fun addValidNumbers(numbers : List<Int?>) {
    val validNumbers = numbers.filterNotNull()
    println(“Sum of valid numbers : ${validNumbers.sum()}”)
    println(“Invalid numbers : ${numbers.size - validNumbers.size}”)
}

只读集合和可变集合

Kotlin的集合设计和Java不同的另一项重要特质是,它把访问集合数据的借口和修改集合数据的接口分开了。这种区别在于最基础的使用集合的接口之中:kotlin.collections.Collection. 使用这个接口可以遍历集合中的元素,获取集合大小,判断集合中是否包含某个元素,以及执行其他从该集合中读取数据的操作。但这个接口没有任何添加或移除元素的方法.
而另外一个kotlin.collections.MutableCollection接口可以修改集合中的数据。它继承了普通的kotlin.collections.Collection接口,它还提供了方法来添加和移除和清空集合等.
把只读集合和可变集合分离的好处在于,如果函数接收Collection而不是MutableCollection作为形参,你就知道它只是读取集合中的数据。如果函数要求你传递给它MutableCollection,可以认为它将会修改数据.
下面一个例子展示使用只读集合与可变集合接口

fun <T> copyElements(source : Collection<T>, target: MutableCollection<T>){
    for(item in source){
        target.add(item)        //向可变的target集合中添加元素
    }
} 
>>> val source : Collection<Int> = arrayListOf(3,5,7)
>>> val target : MutableCollection<Int> = arrayListOf(1)
>>> copyElements(source, target)
>>> println(target)
[1,3,5,7]

使用集合接口时需要牢记一个关键点是只读集合不一定是不可变的. 如果你使用的变量拥有一个只读接口类型,它可能只是同一个集合的众多引用中的一个。任何其他的引用都可能拥有一个可变接口类型。

一个集合多个引用(包含可变集合引用)的情况需要注意线程安全问题,和java一样同一个集合不允许多线程进行修改和读取.

作为平台类型的集合

在kotlin中会吧所有java中的类型作为平台类型.kotlin没有任何关于平台类型的可空性信息,所以编译器允许Kotlin代码将其视为可空或者非空. 同样,Java中声明的集合类型的变量也被视为平台类型.

/*Java*/
interface FileContentProcessor{
    void processContents(File path,byte[] binaryContents, List<String> textContents);
}

这个接口的Kotlin实现需要做出下面的选择:
列表将可能是可空的,因为有些文件是二进制格式,它们的内容不能被表示成文本.
列表中的元素将会是非空的,因为文件中每一行都永远不为null
列表将是只读的,因为表示的是文件的内容,而这些内容不会被改变

下面来看看kotlin中实现的样子:

class FileIndexer : FileContentProcessor{
    override fun processContents(path : File, binaryContents : ByteArray?, textContents: List<String>?)
}

另一个使用集合参数的java接口
/Java/
interface DataParser<T>{
void parseData(String input, List<T> output, List<String> errors)
}
这种情况下需要做出下面的选择
List<String>将是非空的,因为调用者总是需要接收错误消息
列表中的元素将是可空的, 因为不是每个输出列表中的条目都有关联的错误信息.
List<String>将是可变的,因为实现代码需要向其中添加元素.
下面是具体实现的样子:

class PersonParser : DataParser<Person>{
    override fun parseData(input : String, output : MutableList<Person>, errors: MutableList<String?>)
}

同样的Java类型List<String>表示成了不同的Kotlin类型:一种是List<String>? (包含字符串的可空列表) ,一种是List<String>? (包含空字符串的可变列表). 为了做出正确的选择,你可以根据需求做出不同的选择.

对象和基本数据类型的数组

kotlin使用数组

fun main(args : Array<List>){
    for(i in args.indices){
        println(“Argument $i is : ${arg[i]}")
    }
}

Kotlin中一个数组是一个带有类型参数的类,其元素类型被指定为相应的类型参数.
要在Kotlin中创建数组,有下面这些方法供你选择:
arrayOf函数创建一个数组,它包含的元素是为该函数的实参
arrayOfNulls创建一个给定大小的数组,包含的是null元素。当然,它只能用来创建包含元素类型的可空数组
Array构造方法接受数组的大小和一个lambda表达式,调用lambda表达式来创建每一个数组元素

val letters = Array<String>(26){ i -> (‘a’+i).toString }
println(letters.joinToString(“”))

集合转换成数组

val strings = listOf(“a”,”b”,”c”)
println(“%s/%s/%s”.format(*string.toTypeArray()))

和其他类型一样,数组类型的类型参数始终会变成对象类型。如果声明一个Array<Int>,它将会是一个包含装箱整型的数组(它的Java类型将是java.lang.Integer[]).如果你需要创建没有装箱的基本数据类型数组,必须使用一个基本数据类型数组的特殊类.
为了表示基本类型数组,Kotlin提供了若干独立的类,每一种基本数据类型都对应一个。例如,Int类型值的数组叫做IntArray. Kotlin还提供了ByteArray,CharArray,BooleanArray等给其他类型.所有这些类型都被编译成普通的Java基本数据类型数组,比如
int[],byte[],char[]等.这些数组的值存储时并没有装箱,而是使用了更高效的方式.
要创建基本数据类型的数组,有如下几种方法
1,该类型的构造方法接收size参数并返回一个使用对应基本数据类型默认值(通常是0)初始化好的数组

val fiveZeros = IntArray(5)

2,工厂函数(IntArray的intArrayOf,以及其他数组类型的函数)接收变长参数的值并创建存储这些值的数组

val fiveZeroToo = intArrayof(0,0,0,0,0)

3,另一种构造方法,接收一个大小和一个用来初始化每个元素的lambda.

val squares = IntArray(5){i -> (i+1) * (i+1)}
println(squares.joinToString())
1,4,9,16,25

另外kotlin标准库支持一套和集合相同的对于数组的扩展函数。(例如filter,map等)也适用于数组。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容