Обратите внимание: Это не дублирующий вопрос, так как этот вопрос указывает на все методы Iterator
имеет, а не только map
и flatMap
. Поэтому Future.traverse
не является хорошим ответом.
Скажем, у меня есть это простое утверждение:
(1 to 100).toSet.subsets.find(f)
Он отлично работает. Он ленив, не использует много памяти и возвращается, как только будет найден один элемент. Проблема начинается, когда вы хотите распараллелить ее. Вы могли бы сказать, что это Scala, должно быть .par
или Iterator
, но этого нет.
Предлагаемое решение в Интернете - использовать .grouped
, но это не так хорошо, как хотелось бы. Почему?
val it = (1 to 100).toSet.subsets.grouped(1000000).map(_.par.find(f)).flatten
if (it.hasNext) Some(it.next) else None
-
Использует гораздо больше памяти. Я знаю, что это все еще O (1), но позвольте быть идеальным здесь:)
-
Это не идеально параллелизуемо (по закону Амдала). Когда
.grouped
потребляет итератор для следующего блока из миллиона элементов, ожидает только один поток. Это особенно проблематично, если итератор стоит дорого. Кроме того, для создания нового блока должно возникнуть накладные расходы на создание нового набора потоков. -
Производит более сложный/более длинный код (см. пример). Это немного сократило бы код, если
Iterator
имел.nextOption
, но все же.
Есть ли что-нибудь еще, несмотря на то, что я программировал собственную модель производителя-потребителя (итератор - производитель, потоки - это потребители), а затем окончательный шаг сокращения?