Причина в том, что конкретный код медленный, заключается в том, что он работает с примитивами, но использует общие операции, поэтому примитивы должны быть упакованы.(Это могло бы быть улучшено, если бы List
и его предки были специализированными.) Это, вероятно, замедлит вещи примерно в 5 раз.
Кроме того, алгоритмически, эти операции несколько дороги, потому что вы делаетевесь список, а затем составьте новый список, отбросив несколько компонентов промежуточного списка.Если вы сделали это одним махом, то вам было бы лучше.Вы могли бы сделать что-то вроде:
list collect (case e if (e*2>10) => e*2)
но что если вычисление e*2
действительно дорого?Тогда вы могли бы
(List[Int]() /: list)((ls,e) => { val x = e*2; if (x>10) x :: ls else ls }
за исключением того, что это появилось бы в обратном направлении.(Вы можете изменить его, если это необходимо, но для этого необходимо создать новый список, который опять-таки не идеален с точки зрения алгоритма.)
Конечно, у вас возникают те же алгоритмические проблемы в Java, если вы используетеодносвязный список - ваш новый список будет заканчиваться задом наперед, или вам придется создавать его дважды, сначала наоборот, а затем вперед, или вы должны построить его с помощью (нехвостовой) рекурсии (что легко в Scala, нонеприемлемо для такого рода вещей на любом языке, так как вы исчерпаете стек), или вы должны создать изменяемый список, а затем делать вид, что он не изменяем.(Что, кстати, вы можете сделать и в Scala - см. mutable.LinkedList
.)