Lazy Collections(遅延コレクション)とは、コレクションに対する計算を結果に直接アクセスするまで遅延させることを可能にするSwift 2からの特別なメカニズムです。元々、コレクションの標準メソッド(例えば、mapやfilter)は、新しいコレクションの完全に計算された結果を返していましたが、特に大きな配列や変換のチェーンを操作するときに、不要なメモリと時間の浪費を引き起こすことがありました。
問題は、中間コレクションの過剰な作成にあります。mapやfilterを呼び出すたびにデータの新しいコピーが作成され、多数の変換が行われるとプログラムのパフォーマンスが著しく低下します。
解決策は、.lazyプロパティを使用して遅延コレクションを活用することです。Swiftはすべての操作を1つのチェーンに統合し、実際にアクセスする要素のみを計算します。
コードの例:
let array = Array(1...1_000_000) let result = array.lazy.filter { $0 % 2 == 0 }.map { $0 * 3 } print(result.prefix(5)) // 最初の5つの値だけが計算されます
主な特徴:
質問 1: let b = a.lazy.map { ... }はすぐに計算結果を返しますか?
いいえ、.lazyおよびmap/filterメソッドを使用すると、計算結果はデータに直接アクセスするまで(例えば、for-in、first、reduceを通じて)返されません。
コードの例:
let array = [1, 2, 3] let mapped = array.lazy.map { x in print("processing\(x)") return x * 2 } // この段階では何も出力されません let first = mapped.first // ここで計算が実行され、出力が表示されます
質問 2: .lazyの後に元のコレクションに新しい要素を追加すると、後で結果にアクセスするとそれも処理されますか?
いいえ、Lazy Collectionは遅延ビューを作成した時のコレクションの状態を反映します。後で追加された要素は考慮されません。
質問 3: 小さなコレクション(<100要素)で.lzyを使用することは効果的ですか?
いいえ、小さなコレクションでは遅延計算の利益はほとんど感じられず、時には余分なオーバーヘッドがパフォーマンスに悪影響を与えます。
プロジェクトでは、すべてのmap/filterに対して.lzyを無思慮に使用しました。
長所:
短所:
長い変換のチェーンが実際に存在する関数に対してのみ.lzyを使用して、大量のトランザクションデータベースに対するレポートをリファクタリングしました。
長所:
短所: