In the article written by Daniel Korzekwa, he said that the performance of following code:
list.map(e => e*2).filter(e => e>10)
is much worse than the iterative solution written using Java.
Can anyone explain why? And what is the best solution for such code in Scala (I hope it’s not a Java iterative version which is Scala-fied)?
The reason that particular code is slow is because it’s working on primitives but it’s using generic operations, so the primitives have to be boxed. (This could be improved if
Listand its ancestors were specialized.) This will probably slow things down by a factor of 5 or so.Also, algorithmically, those operations are somewhat expensive, because you make a whole list, and then make a whole new list throwing a few components of the intermediate list away. If you did it in one swoop, then you’d be better off. You could do something like:
but what if the calculation
e*2is really expensive? Then you couldexcept that this would appear backwards. (You could reverse it if need be, but that requires creating a new list, which again isn’t ideal algorithmically.)
Of course, you have the same sort of algorithmic problems in Java if you’re using a singly linked list–your new list will end up backwards, or you have to create it twice, first in reverse and then forwards, or you have to build it with (non-tail) recursion (which is easy in Scala, but inadvisable for this sort of thing in either language since you’ll exhaust the stack), or you have to create a mutable list and then pretend afterwards that it’s not mutable. (Which, incidentally, you can do in Scala also–see
mutable.LinkedList.)