Kotlin 集合的变换与聚合

本文介绍了Kotlin中的集合变换与聚合,包括filter、map和flatMap等操作,详细解析了它们的工作原理和使用场景,并通过实例展示了它们在处理集合时的区别,如饿汉式和懒汉式。同时,还简要提到了集合的聚合操作fold。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

Kotlin 高阶函数与内联函数 中我们已经将 Kotlin 的 高阶函数内联函数 讲完了,今天我们来讲 Kotlin 的 集合变换与聚合

二、集合变换与聚合

2.1、集合的变换操作

对于集合来说,最常见的使用方式就是对集合进行遍历,我们来看一下 Java 和 Kotlin 的遍历集合代码:
Java:

// 普通的 for 循环遍历
for(int i = 0; i <= 10; i++) {
	System.out.println(i);
}

// for each 遍历
for(int e : list) {
	System.out.println(e);
}

// forEach 函数
list.forEach((e) - > {
	System.out.println(e);
});

Kotlin:

// 普通的 for 循环遍历
for(i in 0 .. 10) {
	println(i)
}

// for each 遍历
for(e in list) {
	println(e);
}

// forEach 函数
list.forEach {
	println(it);
}

在上面的 forEach 函数里面不能 continue 或者 break,但是我们有需要 break 和 continue 的需求要怎么办呢?其实我们有专用的方法来解决这样的需求,就是集合的 映射操作(Java 在 8 的时候也引入了这些操作,叫 流Stream),如下:

函数名说明
filter保留满足条件的元素
map集合中的所有元素 —— 映射到其他元素构成新集合
flatMap集合中的所有元素 —— 映射到新集合并合并这些集合得到新集合

2.1.1、filter 操作

比如我们要从集合 [1, 2, 3, 4] 中将所有的偶数筛选出来,就可以用 filter 操作来实现,如下:

Java:

 list.stream()
 	.filter(e -> e % 2 == 0);

Kotlin:

list.filter { it % 2 == 0 }

2.1.2、map 操作

比如我们要把集合 [1, 2, 3, 4] 中的所有元素乘以 2,变成一个新集合,就可以用 map 操作来实现,如下:

Java:

 list.stream()
 	.map(e -> e * 2);

Kotlin:

list.map { it * 2 }

上面的 Kotlin 代码还可以写成下面这样:

list.asSequence().map { it * 2 }

这两种写法区别主要是集合的操作是饿汉式的还是懒汉式的,如果加上 asSequence 的话,集合的操作就变成了懒序列了。我们通过下面的代码来解释这两种方式:

Java:

List<Integer> list = new ArrayList<>();
list.addAll(Arrays.asList(1, 2, 3, 4));

list.stream()
		.filter(e -> {
		System.out.println("filter: " + e);
		return e % 2 == 0;
		})
		.map(e -> {
		System.out.println("map: " + e);
		return e * 2 + 1;
		})
		.forEach(e -> {
		System.out.println("forEach: " + e);
		});

Kotlin:

val list = listOf(1, 2, 3, 4)
list.asSequence()
     .filter {
         println("filter: $it")
         it % 2 == 0
     }.map {
         println("map: $it")
         it * 2 + 1
     }.forEach {
         println("forEach: $it")
     }

打印结果如下所示:
懒序列结果

从打印结果可以看出,懒序列的执行方式是集合里面的 1 走一遍完整的流程,走完之后 2 继续走一遍完整的流程…,但是 1 呢在 filter 里面判断是不是偶数就不满足了,然后就是 2 走一遍完整流程,2 是满足 filter 的过滤的,所以 2 就到了 map 里面映射成了 5,然后在 forEach 中输出了,3 和 4 都是同样的流程。

如果我们把 asSequence() 去掉,就变成了饿汉式,代码如下:

val list = listOf(1, 2, 3, 4)
list
	.filter {
		println("filter: $it")
		it % 2 == 0
	}.map {
		println("map: $it")
		it * 2 + 1
	}.forEach {
		println("forEach: $it")
	}

饿汉式结果

从打印结果可以看出,饿汉式在调用 filter 的时候马上就会将集合全部过滤一遍,然后过滤之后的在去执行 map,等所有元素 map 操作都执行好之后,在执行 forEach。

2.1.3、flatMap 操作

flatMap 操作可以看下面的图解:
flatMap 操作

flatMap 的操作就是将一个元素映射成集合,然后再将这些集合合并起来。

2.2、集合的聚合操作

集合除了有上述的变换操作外,集合还有聚合操作,如下:

函数名说明
sum所有元素求和
reduce将元素依次按规则聚合,结果与元素类型一致
fold给定初始化值,将元素按规则聚合,结果与初始化值类型一致

Kotlin 的集合的聚合操作相比来讲没有变换操作重要,这里我就举个 fold 函数的例子吧,如下:

// 计算过程为 10 + 1 + 2 + 3,等于 16
val foldResult1 = arrayOf(1, 2, 3).fold(10, { a, b -> a + b }) 
println(foldResult1)

//计算过程为 10 * 1 * 2 * 3,等于60
val foldResult2 = arrayOf(1, 2, 3).fold(10, { a, b -> a * b })
println(foldResult2)

fold 函数的操作如下:

  1. 第一次执行时,由初始值 10 作为参数 a,由集合中第 0 个元素作为参数 b;
  2. 第二次执行时,第一次执行的返回值作为参数 a,由集合中第 1 个元素作为参数 b;
  3. 依次类推…;
  4. 最终将结果返回。

三 、小结

本篇博客主要讲了 Kotlin 中的集合的变换与聚合,下一节我们讲 Kotin 的 SAM 转换常用高阶函数

四、源码

源码 已上传至 github,有需要可以直接下载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值