Załóżmy, że mam bardzo duży zbiór wartości iterowalnych (w kolejności 100 000 wpisów String, czytanych z dysku jeden po drugim), i robię coś na produkcie kartezjańskim (i zapisuję wynik) na dysku, choć nie pokaże, że tutaj):Scala dla pętli i iteratorów
for(v1 <- values; v2 <- values) yield ((v1, v2), 1)
rozumiem, że jest to po prostu inny sposób pisania
values.flatMap(v1 => values.map(v2 => ((v1, v2), 1)))
to najwyraźniej powoduje całą kolekcję dla każdego flatMap iteracji (lub nawet cały produkt kartezjański?), który ma być przechowywany w pamięci. Jeśli czytasz pierwszą wersję za pomocą pętli for, to oczywiście nie jest konieczne. Najlepiej byłoby, gdyby tylko dwa wpisy (te połączone) zawsze były przechowywane w pamięci.
Gdybym przeformułować pierwszą wersję takiego:
for(v1 <- values.iterator; v2 <- values.iterator) yield ((v1, v2), 1)
zużycie pamięci jest dużo niższy, prowadząc mnie przyjąć, że ta wersja musi być zasadniczo różne. Co dokładnie robi to inaczej w drugiej wersji? Dlaczego Scala nie używa domyślnie iteratorów w pierwszej wersji? Czy jest jakieś przyspieszenie, gdy nie używasz iteratorów w pewnych okolicznościach?
Dzięki! (A także dzięki "lmm", który odpowiedział na wcześniejszą wersję tego pytania)
Jeśli otrzymasz '((v1, v2), 1)' budujesz nową kolekcję zawierającą wszystkie te krotki. Tak więc cały kartezjański produkt będzie musiał być przechowywany w pamięci, nie? –
Niekoniecznie zapisuje się je z powrotem na dysk (za pomocą iskry/HDFS). W przeciwnym razie nie skalowałoby się zbyt dobrze :) – Johannes