breakOut
, упомянутый в другом ответе, разрешается на фабрику строителя для сбора ожидаемого типа map
. Ожидаемый тип map
- mutable.Map[Int, Boolean]
.
Поскольку фабрика компоновщика обеспечивается последовательным сбором, collect
не будет работать параллельно:
scala> val cond1: Int => Boolean = _ % 2 == 0
cond1: Int => Boolean = <function1>
scala> val dataList = 1 to 10
dataList: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> val map: mutable.Map[Int,Boolean] = dataList.par.collect{case p if cond1(p) => println(Thread.currentThread); (p, true)}(breakOut)
Thread[Thread-8,5,main]
Thread[Thread-8,5,main]
Thread[Thread-8,5,main]
Thread[Thread-8,5,main]
Thread[Thread-8,5,main]
map: scala.collection.mutable.Map[Int,Boolean] = Map(10 -> true, 8 -> true, 4 -> true, 6 -> true, 2 -> true)
Вы можете видеть это по имени потока - поток должен содержать имя ForkJoin
-что-то.
Правильный путь
Правильный способ сделать это должен сначала использовать breakOut
с ожидаемым типом, являющимся параллельной картой, чтобы collect
действовал параллельно:
scala> val map: parallel.mutable.ParMap[Int,Boolean] = dataList.par.collect{case p if cond1(p) => println(Thread.currentThread);(p, true)}(breakOut)
Thread[Thread-9,5,main]
Thread[Thread-9,5,main]
Thread[Thread-9,5,main]
Thread[Thread-9,5,main]
Thread[Thread-9,5,main]
map: scala.collection.parallel.mutable.ParMap[Int,Boolean] = ParHashMap(10 -> true, 8 -> true, 4 -> true, 6 -> true, 2 -> true)
и затем вызовите seq
по результату collect
, так как seq
всегда O(1)
.
ОБНОВЛЕНИЕ : только что проверил - похоже, работает корректно с транком, но не с 2.9.1. Финал.
Патч
Но, как вы можете видеть, это тоже не работает, потому что это ошибка, и она будет исправлена в следующей версии Scala. Обходной путь:
scala> val map: parallel.mutable.ParMap[Int, Boolean] = dataList.par.collect{case p if cond1(p) => println(Thread.currentThread);(p, true)}.map(x => x)(breakOut)
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-0,5,main]
Thread[ForkJoinPool-1-worker-8,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
map: scala.collection.parallel.mutable.ParMap[Int,Boolean] = ParHashMap(10 -> true, 8 -> true, 4 -> true, 6 -> true, 2 -> true)
scala> val sqmap = map.seq
sqmap: scala.collection.mutable.Map[Int,Boolean] = Map(10 -> true, 8 -> true, 4 -> true, 6 -> true, 2 -> true)
С примечанием, что окончательный map
будет в настоящее время выполняться последовательно.
В качестве альтернативы, если с вами достаточно parallel.ParMap
, вы можете сделать:
scala> val map: Map[Int, Boolean] = dataList.par.collect{case p if cond1(p) => println(Thread.currentThread);(p, true)}.toMap.seq
Thread[ForkJoinPool-1-worker-2,5,main]
Thread[ForkJoinPool-1-worker-3,5,main]
Thread[ForkJoinPool-1-worker-7,5,main]
Thread[ForkJoinPool-1-worker-1,5,main]
Thread[ForkJoinPool-1-worker-8,5,main]
map: scala.collection.Map[Int,Boolean] = Map(10 -> true, 6 -> true, 2 -> true, 8 -> true, 4 -> true)