33

What is the difference between scala.collections.mutable.ArrayBuilder and scala.collections.mutable.ArrayBuffer? If, for instance, I need to build an Array[Int], which is preferrable to use? Is there any perfomance difference, like in java.lang.StringBuffer and java.lang.StringBuilder?

2 Answers 2

45

ArrayBuilder is a Builder, and builders are meant to be used to construct other collections by adding elements to them. Builders are not usually meant to be used directly in client code.

ArrayBuffer is a Buffer and Seq -- buffers are sequences to which you can efficiently append elements. Sequences come with a lot of auxiliary operations.

You probably need an ArrayBuffer. It is meant to be used as an alternative to the ArrayList in Java. The ArrayBuffer class is a fully-powered sequence collections with all the bulk data operations like foreach, map, filter, zip and friends, unlike ArrayBuilder which is equipped only with += to add elements and result to obtain the array at the end.

One place where you might prefer an ArrayBuilder is when you are instantiating it for a primitive type like Int and you care about performance. In this case the ArrayBuilder variants are specialized for different primitive types and hold an underlying array of a proper primitive type, whereas an ArrayBuffer always holds an object array underneath -- every primitive you add to it undergoes boxing.

To instantiate an array buffer:

new ArrayBuffer[Int] // gives you an array buffer that will hold boxed integers

To instantiate an array builder:

new ArrayBuilder.ofInt // gives you a manually specialized array builder that will hold real primitives
Sign up to request clarification or add additional context in comments.

3 Comments

The short answer is that Builder are (semi-) internal classes meant for those writing new collections classes (whether as part of the standard library or extensions to it).
Great answer. In my case, it seems, I need an ArrayBuilder: I need to add elements in a while loop to 'something', and then transform this 'something' in an Array (it has to be an array, for java interoperability). This 'something' should be an ArrayBuilder, based on this info.
If you know the exact primitive type for the elements, use an ArrayBuilder to get an appropriate array type back. If you use ArrayBuffer, you can still play tricks to get the array out of it, but it will have the type Object[] from the Java point of view, that is, Array[AnyRef] in Scala terms.
11

I timed it and building an array with ArrayBuilder is noticeably faster:

With ArrayBuffer:

real    0m40.348s
user    0m29.544s
sys 0m1.017s

With Array Builder:

real    0m8.392s
user    0m4.769s
sys 0m0.330s

My code:

import scala.collection.mutable.{ArrayBuffer, ArrayBuilder}

object MyObject {
    def main(args: Array[String]) {

        for (i <- 0 until 100) {
            arrayBuilderMade
            // or arrayBufferMade

        }
    }

    def arrayBufferMade {

        var aBuffer = new ArrayBuffer[Int]()

        for (i <- 0 until 1000000) {
            aBuffer += i
        }

        println(aBuffer.toArray.length)
    }

    def arrayBuilderMade {

        var aBuilder = new ArrayBuilder.ofInt

        for (i <- 0 until 1000000) {
            aBuilder += i
        }

        println(aBuilder.result.length)
    }
}

And

time scala my_code.scala

1 Comment

The difference will be way less (almost negligible) for non-primitive type (e. g. String). Boxing/unboxing of Int takes its toll.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.