ArrayList
is a widely misused "default" List
in Java. It has terrible performance when elements are added/removed frequently, but works pretty well as a replacement for Array
. But what about Scala?
- What is Scala's default collection?
- What Scala collection has characteristics similar to
ArrayList
? - What's a good replacement for
Array
in Scala?
So here are the answers for these:
What is Scala's default collection?
Scala's equivalent of Java's
List
interface is the Seq
. A more general interface exists as well, which is the GenSeq
-- the main difference being that a GenSeq
may have operations processed serially or in parallel, depending on the implementation.
Because Scala allows programmers to use
Seq
as a factory, they don't often bother with defining a particular implementation unless they care about it. When they do, they'll usually pick either Scala'sList
or Vector
. They are both immutable, and Vector
has good indexed access performance. On the other hand, List
does very well the operations it does well.
What Scala collection has characteristics similar to ArrayList
?
That would be
scala.collection.mutable.ArrayBuffer
.
What's a good replacement for Array
in Scala?
Well, the good news is, you can just use
Array
in Scala! In Java, Array
is often avoided because of its general incompatibility with generics. It is a co-variant collection, whereas generics is invariant, it is mutable -- which makes it's co-variance a danger, it accepts primitives where generics don't, and it has a pretty limited set of methods.
In Scala,
Array
-- which is still the same Array
as in Java -- is invariant, which makes most problems go away. Scala accepts AnyVal
(the equivalent of primitives) as types for its "generics", even though it will do auto-boxing. And through the "enrich my library" pattern, ALL of Seq
methods are available to Array
.
So, if you want a more powerful
Array
, just use an Array
.What about a collection that shrinks and grows?
The default methods available to all collections all produce new collections. For example, if you do this:
--
--
--
Then newCollection will be a new collection, while
Then newCollection will be a new collection, while
xs
will still be the same as before this command. This is true no matter what firstCollection was: Array
, List
, etc.
Naturally, this has a cost -- after all, you are producing a new collection. Scala's immutable collections are much better at handling this cost because they are persistent, but it depends on what operation is executed.
No collection can do much about
filter
, but a List
has excellent performance on generating a new collection by prepending an element or removing the head -- the basic operations of a stack, as a matter of fact. Vector
has good performance on a bunch of operations, but it only pays if the collection isn't small. For collections of, say, up to a hundred elements, the overall cost might exceed the gains.
So you can actually add or remove elements to an
Array
, and Scala will produce a new Array
for you, but you'll pay the cost of a full copy when you do that.
Scala mutable collections add a few other methods. In particular, the collections that can increase or decrease size -- without producing a new collection -- implement the
Growable
and Shrinkable
traits. They don't guarantee good performance on these operations, though, but they'll point you to the collections you want to check out.
Comments
Post a Comment