Reputation:
Java code:
Collection<MethodInfo> items = getItems();
MethodInfo[] itemsArray = items.toArray(new MethodInfo[items.size()]);
I wonder, what would be the equivalent code in Scala?
val items: Seq[MethodInfo] = getItems
val itemsArray: Array[MethodInfo] = ???
Upvotes: 3
Views: 7780
Reputation: 33019
As @SpiderPig pointed out in his comment, you can simply call items.toArray
to convert the sequence to an Array. I'm thinking you're probably confused by the fact that you have to supply a target array in Java, but in Scala you just call toArray
with no arguments.
The reason you have to supply the array in Java has to do with type erasure. The Java compiler doesn't know what type of array to create at compile time, and since Java arrays aren't generic, they need a concrete type in order to be instantiated.
The Java implementation of toArray
uses a trick to get around this limitation. By passing in an array of the desired type, the JVM can use reflection on that array to instantiate an array to create a new array of the correct type. (You can actually pass a 0-element array to the toArray
method and it will allocate an array of the correct size. The toArray
method actually delegates this work to Arrays.copyOf
, which then uses reflection to create the copy.)
Scala takes a different approach. The Scala compiler does a lot more work behind the scenes than the Java compiler (default arguments, implicit conversions, implicit parameters, etc). You can tell that there's some compiler magic at work if you look at the implementation for toArray
:
def toArray[B >: A : ClassTag]: Array[B] = {
if (isTraversableAgain) {
val result = new Array[B](size)
copyToArray(result, 0)
result
}
else toBuffer.toArray
}
The ClassTag
in the generic type is requiring the compiler to supply the class information. This allows the JVM to instantiate an array of the correct type and size for your final result. This means you don't have to supply an array because the Scala library has the means to create one of the correct type and size for you.
Upvotes: 7
Reputation: 7110
The only reason Collection#toArray(T[] a)
exists in Java is because of type erasure. At runtime, Java doesn't know what type T
is, so an array of type T[]
cannot be created. Since you must create an array of the correct type yourself, it's in your best interest to allocate one of the correct size to avoid wasting space or making Java allocate another one.
If you use Collection#toArray()
instead (passing no array), Java will allocate an array of the correct size automatically, but it will be Object[]
since there is no type information.
Scala's toArray method is a bit more advanced:
def toArray[B >: A](implicit arg0: ClassTag[B]): Array[B]
Basically, it uses an implicit argument to provide the runtime type information so an array of the correct type can be instantiated automatically. You can use @SpiderPig's code without having to create the array yourself, and you don't have to worry about size.
Upvotes: 2