前言
在介绍了集合的基本操作后Kotlin 集合 基本介绍 - Z同学 (zinyan.com),本篇文章主要介绍集合的进阶操作:
映射转换,合拢转换,关联转换,集合的几种参数数据过滤。
转换
所谓的转换,就是在保持原有集合数据不变的情况下,基于原集合数据和自定义的判断逻辑创建一个新的集合。
简化:用老集合的数据,创建一个新的集合。两个集合互相独立。
List和Set的映射转换
通过Kotlin提供的map()
的一系列方法我们可以针对集合做一个新的映射生成。
示例1:
代码语言:javascript复制fun main(string: Array<String>) {
//创建一个 set 集合对象 是int类型的 并且可以编辑的数组
val mem = mutableSetOf(1,2,3)
println(mem) //可以得到 [1,2,3] 的输出结果
//进行映射操作
val maps = mem.map { it *3 } //将所有参数进行*3 操作
//针对mem 进行修改后,maps会修改么?
mem.remove(3)
println(maps) //可以得到 [3,6,9] 的输出结果
println(mem)
}
//输出
[1, 2, 3]
[3,6, 9]
[1, 2]
可以看到,我们针对老数据进行修改后,新集合数据没有变动。
针对新集合操作后,老数据也不会产生变动。两个集合是独立的。
如果,我们在映射的时候,不只是想利用参数,还想利用下标呢?有方法:mapIndexed
示例2:
代码语言:javascript复制fun main(string: Array<String>) {
//创建一个 set 集合对象 是int类型的
val mem = mutableSetOf(1, 2, 3)
println(mem) //可以得到 [1,2,3] 的输出结果
//进行映射操作
val maps = mem.mapIndexed { index, i ->
//index 就是下标值
// i 就是参数值 参数值,就是两个数据的返回值
i index
}
println(maps)
}
//输出
[1, 2, 3]
[1, 3, 5]
我们也可以根据结果,映射成其他类型的集合
示例3:
代码语言:javascript复制fun main(string: Array<String>) {
//创建一个 set 集合对象 是int类型的
val mem = mutableSetOf(1, 2, 3)
println(mem) //可以得到 [1,2,3] 的输出结果
//进行映射操作
val maps = mem.mapIndexed { index, i ->
if(index==2){
"这是个2"
}else{
"Index:$i"
}
}
println(maps)
}
//输出
[1, 2, 3]
[Index:1, Index:2, 这是个2]
类似的方法还有:
mapNotNull()
, mapIndexedNotNull()
等可以通过传null。来过滤掉定义的值
示例:
代码语言:javascript复制fun main(string: Array<String>) {
//创建一个 set 集合对象 是int类型的
val mem = mutableSetOf(1, 2, 3)
println(mem) //可以得到 [1,2,3] 的输出结果
//进行映射操作
val maps = mem.mapNotNull {
if (it == 1) { //过滤掉参数值为1的数据
null
} else
it
}
println(maps)
}
//输出
[1, 2, 3]
[2, 3]
Map的映射转换
相对于List和Set 对象。Map有key和value 我们能够通过mapKeys
和mapValues
针对map的特性进行转换
示例1:我们映射了一个新的map对象,将全部的key都进行了替换。
代码语言:javascript复制fun main(string: Array<String>) {
//创建一个 map 集合对象 是int类型的
val mem = mapOf("key1" to 10,"key2" to 20,"key3" to 3)
println(mem)
val mpas = mem.mapKeys {
"Zinyan-${it.key}"
}
println(mpas)
}
//输出
{key1=10, key2=20, key3=3}
{Zinyan-key1=10, Zinyan-key2=20, Zinyan-key3=3}
示例2:映射一个新的map对象,将全部的value进行替换
代码语言:javascript复制fun main(string: Array<String>) {
val mem = mapOf("key1" to 10,"key2" to 20,"key3" to 3)
println(mem)
val mpas = mem.mapValues {
it.value 1
}
println(mpas)
}
//输出
{key1=10, key2=20, key3=3}
{key1=11, key2=21, key3=4}
同时,也有null方法
类似的方法还有:
mapNotNull()
, 可以通过传null。来过滤掉指定的值。
合拢转换 Zip
关键字就是zip
函数。能够将两个集合数组合并成一个二维数组的情况。
合并后的数据是一个Pair对象的List集合,合并后的对象是一个List<Pair>
对象。
示例1:
代码语言:javascript复制fun main(string: Array<String>) {
val n1 = listOf("a", "b", "c", "d")
val n2 = listOf("ZZ", "XX", "YY")
val ss = n1 zip n2 //n1和n2的合并
println(ss)
val zz = ss zip n1 // 合并结果再次和n1 合并
println(zz)
val sz = n1 zip n1 //集合和自己合并
println(sz)
}
//输出
[(a, ZZ), (b, XX), (c, YY)]
[((a, ZZ), a), ((b, XX), b), ((c, YY), c)]
[(a, a), (b, b), (c, c), (d, d)]
通过数据我们可以知道。两个集合的长度,在合并后结果是按照下标共有区域进行的合并。
也就是哪个集合长度最小,那么就按照最小长度进行合并。
如果我们希望zip 合并后的数据是一个普通集合该怎么做?
示例2:
代码语言:javascript复制fun main(string: Array<String>) {
val n1 = listOf("a", "b", "c", "d")
val n2 = listOf("ZZ", "XX", "YY")
val ss = n1.zip(n2) { n1, n2 ->
"结果:$n1:$n2"
} //n1和n2的合并
println(ss)
}
//输出
[结果:a:ZZ, 结果:b:XX, 结果:c:YY]
这个例子输出的就是一个List<String>
。我们也可以基于该方式,合并后其他数据格式。
针对已经合并的集合,我们可以调用unzip()方法,分解
示例3:
代码语言:javascript复制fun main(string: Array<String>) {
val n1 = listOf("a", "b", "c", "d")
val n2 = listOf("ZZ", "XX", "YY")
val ss = n1 zip n2
println(ss)
val sss = ss.unzip()
println(sss)
println("First:${sss.first}")
println("Second:${sss.second}")
}
//输出
[(a, ZZ), (b, XX), (c, YY)]
([a, b, c], [ZZ, XX, YY])
First:[a, b, c]
Second:[ZZ, XX, YY]
关联转换 associate
关联转换允许从集合元素和与其关联的某些值构建map。相对于其他的转换,关联转换会根据逻辑转换成Map对象。
示例1:
代码语言:javascript复制fun main(string: Array<String>) {
val n1 = listOf("aa", "bb", "c", "dddd")
//关联集合,计算value的值
val ass = n1.associateWith {
it.length
}
println(ass)
println("keys:${ass.keys}")
println("values:${ass.values}")
val ss = n1.associate {
Pair(it, it)
}
println(ss)
}
//输出
{aa=2, bb=2, c=1, dddd=4}
keys:[aa, bb, c, dddd]
values:[2, 2, 1, 4]
{aa=aa, bb=bb, c=c, dddd=dddd}
还有其他的几种函数。功能都是转换
associateBy
,associateTo
等等
将集合对象的值作为关联转换后的值。
示例:
代码语言:javascript复制fun main(string: Array<String>) {
val n1 = listOf("aa", "bb", "c", "dddd")
//关联集合,计算计算key
val ss = n1.associateBy {
it.first()
}
println(ss)
}
//输出
{a=aa, b=bb, c=c, d=dddd}
二维数组的一维输出 flatten
我们可以通过flatten
和flatMap
函数。进行拆解多维嵌套集合
示例1:
代码语言:javascript复制val n1 = listOf(setOf(1,2,3), setOf("a","b","c"), setOf(9,8,7,6))
println(n1)
val ss = n1.flatten()
println(ss)
//输出
[[1, 2, 3], [a, b, c], [9, 8, 7, 6]]
[1, 2, 3, a, b, c, 9, 8, 7, 6]
示例2:
代码语言:javascript复制fun main(string: Array<String>) {
val s1 = listOf(listOf(1, "b", 4), listOf("a", "b", "c"))
println(s1)
val sss =s1.flatMap {
it.asIterable()
}
println(sss)
}
//输出
[[1, b, 4], [a, b, c]]
[1, b, 4, a, b, c]
flatMap对象遍历每个元素后,它需要的返回值是Iterable
对象才行
过滤 filter
针对集合的常用需求。Kotlin通过使用lambda表达式来实现匹配判断。
该表达式返回true:说明给定元素匹配,false:表明给定元素不匹配。
过滤操作并不会针对原始数据做处理
过滤关键函数是filter()
示例1:
代码语言:javascript复制fun main(string: Array<String>) {
val word = mutableListOf("A", "B", "C", "E", "D", "F")
val ss = word.filter { it.equals("F") }
println(word)
println(ss)
}
//输出
[A, B, C, E, D, F]
[F]
其中filter只能检测元素的值,进行过滤。如果我们需要元素下标值参与。那么就可以使用filterIndexed{}
,
但是我们如果有需求,得到集合中取反向呢?那么我们可以使用filterNot
示例2:我们需要获取集合中不是F的字符 filterNot
fun main(string: Array<String>) {
val word = mutableListOf("A", "B", "C", "E", "D", "F")
val ss = word.filterNot { it ->
it.equals("F")
}
println(word)
println(ss)
}
//输出
[A, B, C, E, D, F]
[A, B, C, E, D]
filterIsInstance 返回给定类型的元素
主要是处理泛型List 的筛选
示例1:
代码语言:javascript复制fun main(string: Array<String>) {
val word = listOf(null, 1, "A", 1.0f, "zzzz")
println(word)
//获取数组中的字符串
val ss = word.filterIsInstance<String>()
println(ss)
val num = word.filterIsInstance<Int>()
println(num)
}
//输出
[null, 1, A, 1.0, zzzz]
[A, zzzz]
[1]
过滤掉空值
示例
代码语言:javascript复制fun main(string: Array<String>) {
val word = listOf(null, 1, "A", 1.0f, "zzzz")
println(word)
//获取数组中的字符串
val ss = word.filterNot {
it == null
}
println(ss)
}
//输出
[null, 1, A, 1.0, zzzz]
[1, A, 1.0, zzzz]
划分 partition 过滤
可以将集合划分为两个集合结果。将会得到过滤结果集和过滤剩下结果集。
示例:
代码语言:javascript复制fun main(string: Array<String>) {
val num = listOf("A", "B", "C", "D", "E", "F")
val (n1, n2) = num.partition { it.equals("C") || it.equals("D") }
println(n1)
println(n2)
}
//输出
[C, D]
[A, B, E, F]
检测 any,none,all
- 如果至少有一个元素匹配,那么
any()
返回true
。 - 如果没有元素匹配,那么
none()
返回true
。 - 如果所有元素都匹配,那么
all()
返回true
。注意,在一个空集合上调用 all() 都会返回 true 。这种行为在逻辑上被称为 [*vacuous truth*](https://en.wikipedia.org/wiki/Vacuous_truth)。
示例1:
代码语言:javascript复制fun main(string: Array<String>) {
val num = listOf("A", "B", "C", "D", "E", "F")
//检测list中是否有A
println(num.any { it.equals("A") })
//和any检测相反
println(num.none { it.equals("A") })
//所有项都必须是A的时候就返回ture。
println(num.all { it.equals("A") })
}
//输出
true
false
false
如果any和none不带比较参数时。就是检测List 是否为空
示例2:
代码语言:javascript复制fun main(string: Array<String>) {
val num = listOf("A", "B", "C", "D", "E", "F")
//如果不带参数时,就会检测集合是否有元素。
println(num.any())
//和any检测相反
println(num.none())
val num1 = listOf(null) //空元素也是有元素
println(num1.any())
val num2 = listOf<String>() //空元素,所以返回false
println(num2.any())
}
//输出
true
false
true
false