Reputation: 858
From what I have read, one should prefer to use generic Seq when defining sequences instead of specific implementations such as List
or Vector
.
Though I have parts of my code when a sequence will be used mostly for full traversal (mapping, filtering, etc) and some parts of my code where the same sequence will be used for indexing operations (indexOf, lastIndexWhere).
In the first case, I think it is better to use LinearSeq
(implem is List
) whereas in the second case it is better to use IndexedSeq
(implem is Vector
).
My question is: do I need to explicitly call the conversion method toList
and toIndexedSeq
in my code or is the conversion done under the hood in an intelligent manner ? If I use these conversions, is it a penalty for performance when going back and forth between IndexedSeq
and LinearSeq
?
Thanks in advance
Upvotes: 1
Views: 192
Reputation: 858
I have done the same for indexOf and Vector is also more performant
val l = List.range(1,1000000)
val a = Vector.range(1,1000000)
import System.{currentTimeMillis=> milli}
val startList = milli
l.indexOf(500000)
println("time for list index operation : " + (milli - startList))
val startVector = milli
a.indexOf(500000)
println("time for vector index operation : " + (milli - startVector))
Output :
time for list index operation : 36
time for vector index operation : 33
So I guess I should use Vector all the times in internal implementations but I must use Seq when I build interface as specified here : Difference between a Seq and a List in Scala
Upvotes: 0
Reputation: 24812
Vector
will almost always out-perform List
. Unless your algorithm uses only ::
, head
and tail
, Vector
will be faster than List
.
Using List
is more of a conceptual question on your algorithm (data is stack-structured, only accessing head/tail, only adding elements by prepending, use of pattern matching (which can be used with Vector
, just feels more natural to me to use it with List
)).
You might want to look at Why should I use vector in scala
Now for some nice number to compare (obviously not a 'real' benchmark, but eh) :
val l = List.range(1,1000000)
val a = Vector.range(1,1000000)
import System.{currentTimeMillis=> milli}
val startList = milli
l.map(_*2).map(_+2).filter(_%2 == 0)
println(s"time for list map/filter operations : ${milli - startList}")
val startVector = milli
a.map(_*2).map(_+2).filter(_%2 == 0)
println(s"time for vector map/filter operations : ${milli - startVector}")
Output :
time for list map/filter operations : 1214
time for vector map/filter operations : 364
Edit : Just realized this doesn't actually answer your question. As far as I know, you will have to call toList/toVector yourself. As for performances, it depends on your sequence, but unless you're going back and forth all the time, it shouldn't be a problem.
Once again, not a serious benchmark, but :
val startConvToList = milli
a.toList
println(s"time for conversion to List: ${milli - startConvToList}")
val startConvToVector = milli
l.toVector
println(s"time for conversion to Vector: ${milli - startConvToVector}")
Output :
time for conversion to List: 48
time for conversion to Vector: 18
Upvotes: 1