数组、集合与序列

数组

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

如:使用构造函数

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

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

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

IntArray 与 Array

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

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

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

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

StringArray 与 Array

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

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

判断

函数 含义
all 判断集合中是否所有元素都满足表达式
any 判断集合中是否有元素满足表达式
count 统计集合中有多少元素满足表达式
find 找到第一个满足表达式的元素
firstOrNull 同 find
fun main(args: Array) {
    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) {
    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) {
    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)

可变与不可变

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

数组、集合与序列_第1张图片
接口关系

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


序列

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

初始化

有两种方式:

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

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

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

操作

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

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

fun main(args: Array) {
    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. 序列的操作不是内联的,但集合的操作是内联的。因此,能用集合时尽量使用集合。


你可能感兴趣的:(数组、集合与序列)