面试题答案
一键面试常见瓶颈点
- 频繁创建中间集合:在流式处理中,每次调用中间操作(如
map
、filter
等)都会创建一个新的中间集合,这会增加内存开销和处理时间。例如:
val list = (1..10000).toList()
val result = list
.map { it * 2 }
.filter { it % 3 == 0 }
.map { it.toString() }
这里进行了多次中间集合创建。
2. 不必要的操作:在流处理过程中执行了一些对最终结果没有实际影响或者可以提前避免的操作。例如在 filter
之前进行复杂的 map
操作,而 filter
可能会过滤掉大部分数据,导致之前的 map
操作浪费。
val list = (1..10000).toList()
val result = list
.map { veryComplexTransformation(it) }
.filter { it % 2 == 0 }
如果 veryComplexTransformation
很耗时,而大部分结果会被 filter
掉,就造成性能浪费。
3. 终端操作的选择不当:不同的终端操作(如 toList
、sum
、find
等)性能不同。例如使用 toList
将流结果收集到列表,而实际上只需要一个单一值(如求和),使用 toList
就会产生不必要的开销。
val list = (1..10000).toList()
val sum = list
.map { it * 2 }
.toList()
.sum()
这里先收集到列表再求和,比直接在流上求和多了一步收集操作。
优化方法
- 减少中间集合创建:尽可能将多个中间操作合并,让流处理管道更紧凑。例如:
val list = (1..10000).toList()
val result = list
.map { it * 2 }
.filter { it % 3 == 0 }
.joinToString(", ") { it.toString() }
这样减少了 map { it.toString() }
产生的中间集合。
2. 合理安排操作顺序:先进行过滤操作,减少后续操作的数据量。例如:
val list = (1..10000).toList()
val result = list
.filter { it % 2 == 0 }
.map { veryComplexTransformation(it) }
先过滤掉一半数据,再进行复杂的 map
操作,减少了不必要的计算。
3. 选择合适的终端操作:如果只需要一个单一值,直接使用相应的终端操作。例如:
val list = (1..10000).toList()
val sum = list
.map { it * 2 }
.sum()
直接在流上求和,避免了不必要的收集操作。