数组、集合与序列

数组

方法 含义
arrayOf 创建一个指定类型的数组,数组中的元素就是函数的实参
arrayOfNulls 创建一个指定大小的数组,默认时数组中的元素都为 null
Array 构造函数 需要指定大小,并提供 lambda 表达式获取每一个元素
intArrayOf等 创建一个 int[]

如:使用构造函数

fun main(args: Array<String>) {
    val a = Array(26) { i ->
        ('a' + i).toString()
    }
    println(a.joinToString(separator = ",")) // a - z 所有的字母
}

lambda 得到的参数为当前下标,返回值是当前下标对应的元素。

使用 Array<> 创建的数组对应到 Java 中将是包装类的数组。而要使用基本数据类型的数组,需要使用 intArrayOf 、IntArray 类似的方法。

IntArray 与 Array<Int>

kt 中定义数组有两种方式:一种通过 IntArray,一种通过 Array<Int>。前者会转换成 int[],后者会转换成 Integer[]

val b: IntArray = IntArray(2)
println(b[0]::class.java) // int

val a: Array<Int> = Array(2, { it })
println(a[0]::class.java) // java.lang.Integer

由于 Array<Int> 元素是一个对象,因此创建 Array<Int> 时,必须指定初始化元素的方法。

StringArray 与 Array<String>

前者是一个类,并不是一个数组;后组是 String[]

    val b: Array<String> = Array<String>(2, { it -> "$it" })
    println(b::class.java) // class [Ljava.lang.String;
    val a = StringArray()
    println(a::class.java) // class com.sun.xml.internal.fastinfoset.util.StringArray

集合

kt 中没有自己的集合类库,全部采用的是 java 标准的集合类。

创建

集合类型 只读 可变
List listOf mutableListOf、arrayListOf
Set setOf mutableSetOf、hashSetOf、linkedSetOf、sortedSetOf
Map mapOf mutableMapOf、hashMapOf、linkedMapOf、sortedMapOf

下面的代码中的 javaClass 等价于 java 中的 getClass() 函数。

    val list = arrayListOf("A","B")
    list.add("aa")
    println(list.javaClass) // java.util.ArrayList

    val list2 = listOf<String>()
    // list2 中没有 add / remove 方法,因为 listOf 返回的是一个只读的 List
    println(list2.javaClass) // kotlin.collections.EmptyList

    val set = hashSetOf("A","B")
    println(set.javaClass) // java.util.HashSet

    val map = hashMapOf<Int,String>()
    println(map.javaClass)  // java.util.HashMap
}

操作集合的 api

filter 与 map

函数 含义
filter 过滤掉集合中不需要的元素
map 对每一个元素进行操作,并将结果存入新的集合
filterKeys 操作 map,过滤掉返回 false 的键值对。参数为每一个 key
filterValues 操作 map,过滤掉返回 false 的键值对。参数为每一个 value
mapKeys 操作 map,对每一个 key 进行映射
mapValues 操作 map,对每一个 value 进行映射
filterNotNull 过滤掉集合中的 null 元素
fun main(args: Array<String>) {
    val list = listOf(1, 2, 3, 4)
    println(list.filter { it % 2 == 0 }) // [2, 4]

    println(list.map { it * 2 }) // [2, 4, 6, 8]

    val map = mapOf(1 to "s1", 2 to "s2")
    println(map.filterKeys { it % 2 == 0 })  // {2=s2}
    println(map.filterValues { it.contains("1") }) // {1=s1}
    // 返回结果会当作新 key
    println(map.mapKeys { it.key * 2 }) // {2=s1, 4=s2}
    println(map.mapValues { "${it.value}--" }) // {1=s1--, 2=s2--}
}

filterNotNull 用于过滤一个集合中所有的 null 值,并将非 null 存储在一个新的集合中返回:

fun main(args:Array<String>){
    // 声明一个元素可空的集合
    val l = listOf(1,3,3,null,324,null,423)
    val result = l.filterNotNull() // 其类型为 List<Int> ,其中元素不可能为 null
    println(result.size)// 5 过滤掉所有的 null
}

判断

函数 含义
all 判断集合中是否所有元素都满足表达式
any 判断集合中是否有元素满足表达式
count 统计集合中有多少元素满足表达式
find 找到第一个满足表达式的元素
firstOrNull 同 find
fun main(args: Array<String>) {
    val list = listOf(1, 4, 3, 4,8)

    println(list.all(::test)) // false
    println(list.any(::test)) // true
    println(list.count(::test)) // 3
    println(list.find(::test)) // 4
    println(list.firstOrNull(::test)) // 4
}
fun test(a:Int) = a % 2 == 0

groupBy

将所有元素按不同特征划分为不同的组。每一个分组都会存储在一个列表中,键为对应的特征。示例中会按元素是否为偶数进行分组。

fun main(args: Array<String>) {
    val list = listOf(1, 4, 3, 4, 8)
    println(list.groupBy(::test)) // {1=[1, 3], 0=[4, 4, 8]}
}

fun test(a: Int) = a % 2

flat 系列

flat 将多个列表合并成一个列表。

函数 含义
flatMap 首先对集合中的元素进行映射,将映射结果进行合并
flatten 合并多个集合

所示代码中,第一个先将 books 映射成一个列表,然后将该列表合并。第二个是直接将一系列的列表合并成一个。

fun main(args: Array<String>) {
    val b1 = Book("b1", listOf("ab11","ab12"))
    val b2 = Book("b2", listOf("ab21","ab22"))
    val b3 = Book("b3", listOf("ab31","ab32"))
    val books = listOf(b1,b2,b3)

    println(books.flatMap { it.authors }) // [ab11, ab12, ab21, ab22, ab31, ab32]

    val ll = listOf(listOf("1","2"), listOf("232","fda"))

    println(ll.flatten())//[1, 2, 232, fda]
}

class Book(val name:String,val authors:List<String>)

可变与不可变

kt 在设计接口时,将访问与修改接口分开了。Collection 只提供访问的 api ,而 MutableCollection 提供了修改的 api。

接口关系

一般使用时,尽量使用不可变的集合;真要需要时,才使用可修改的。


序列

上述的每一个操作都会返回一个集合,所以当链式使用 filter ,map,flat 等操作时,会产生大量的中间集合。如果集合的数据特别大,则内存开销会非常大。而使用 序列不需要额外的开销

初始化

有两种方式:

  1. 使用 asSequence 将任何集合转为序列,使用 toList 将任何序列转为集合

2.使用 generateSequence 直接生成一个序列。该方法需要指定一个初始值,并提供一个由前一个元素生成下一个元素的表达式。

fun main(args: Array<String>) {
    val s = generateSequence(0) { it+1 }
    val r = s.takeWhile { it < 10 }
    println(r.sum()) // 45
}

操作

序列的操作是惰性的:只有在获取结果的时候才会执行所有的操作,在中间不会执行任何操作

相较于序列,集合在每调用一个方法后会立即执行,并将下一个操作应用到得到的结果上。

fun main(args: Array<String>) {
    val l = listOf(1, 2, 3, 4, 5)
    // 该代码不会输出任何语句
    l.asSequence().map { println(it);it * it }.filter { println("filter ${it}");it % 2 == 0 }
    // 调用 asList 后才会有输出
    l.asSequence().map { println("map ${it}");it * it }.filter { println("filter ${it}");it % 2 == 0 }.toList()
}

执行逻辑

序列中的所有操作是按顺序应用在每一个元素上:处理完第一个元素后,再处理第二个。因此,序列中有些元素根本不会发生任何变化,如果在轮到它之前就已经得到结果。

与集合比较

  1. 序列的操作是惰性的。因此,如果要处理的数据量比较大,可以使用序列,以节省内存。

  2. 序列的操作不是内联的,但集合的操作是内联的。因此,能用集合时尽量使用集合。


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

推荐阅读更多精彩内容