list
などの遅延コレクションに変換すると、すべてのフィルター操作 (またはその他のものなど) を 1 回のパスで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 は実行する操作 (ここでは 2 つの s) を追跡しますがfilter
、結果が実際にアクセスされる (ここでは への呼び出しを介して.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
。それらはすべて遅延計算されます (したがって、1 パスの側面が適用されます) が、複数回反復できるかどうか (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
: filter
s と最初の両方foreach
が 1 回の反復で実行されます。が消費されたため、 2 番目foreach
は何もしません。Iterator
結果はメモリに保存されません。
View
: どちらのforeach
呼び出しでも、コレクションに対して独自の単一パスの反復処理が行われ、filters
. 結果はメモリに保存されません。
Stream
: filter
s と最初の両方foreach
が 1 回の反復で実行されます。結果のフィルタリングされたコレクションは、それぞれが表示できるようにメモリに保存されますforeach
。