如果您list变成一个惰性集合,例如 an Iterator,那么您可以一次性应用所有过滤器操作(或其他类似的操作map):
val list = (1 to 12).toList
val doubleFiltered: List[Int] =
list.iterator
.filter(_ % 2 == 0)
.filter(_ % 3 == 0)
.toList
println(doubleFiltered)
当您使用 将集合转换为 Iterator 时.iterator,Scala 将跟踪要执行的操作(这里是两个filters),但会等待执行它们直到实际访问结果(这里是通过对 的调用.toList)。
所以我可能会像这样重写你的代码:
val list = (1 to 12).toList
val evens = list.iterator.filter(_ % 2 == 0)
val result =
if(someCondition)
evens.filter(_ % 3 == 0)
else
evens.filter(_ % 5 == 0)
result foreach println
根据您想要做什么,您可能需要一个Iterator、一个Stream或一个View。它们都是惰性计算的(因此将应用一次性方面),但它们在是否可以多次迭代(Stream和View)或是否保留计算值以供以后访问(Stream)等方面有所不同。
要真正看到这些不同的惰性行为,请尝试运行这段代码并设置<OPERATION>为toList、iterator、view或toStream:
val result =
(1 to 12).<OPERATION>
.filter { e => println("filter 1: " + e); e % 2 == 0 }
.filter { e => println("filter 2: " + e); e % 3 == 0 }
result foreach println
result foreach println
这是您将看到的行为:
List(或任何其他非惰性集合):每个filter都需要对集合进行单独的迭代。生成的过滤集合存储在内存中,以便每个foreach都可以显示它。
Iterator: filters 和 firstforeach都是在一次迭代中完成的。第二个foreach什么都不做,因为Iterator已经消耗了。结果不存储在内存中。
View:这两个foreach调用都会导致它们自己对集合进行单遍迭代以执行filters. 结果不存储在内存中。
Stream: filters 和 firstforeach都是在一次迭代中完成的。生成的过滤集合存储在内存中,以便每个foreach都可以显示它。