2011-02-17 22 views
9

esto es un poco una pregunta general, pero me preguntaba si alguien podría aconsejarme sobre cuáles serían las ventajas de trabajar con matrices vs arrayseq. Por lo que he visto, Array es la representación de scala de Java Arrays y no hay demasiados miembros en su API, mientras que Arrayseq parece contener una API mucho más rica. gracias por cualquier consejoscala - array vs arrayseq

Respuesta

32

En realidad, hay cuatro clases diferentes se podía elegir para conseguir la funcionalidad mutable tipo array.

Array + ArrayOps 
WrappedArray 
ArraySeq 
ArrayBuffer 

Array es una matriz de Java simple y llano. Es, de lejos, la mejor forma de acceder a niveles bajos de matrices de primitivas. No hay gastos generales. También puede actuar como las colecciones de Scala gracias a la conversión implícita a ArrayOps, que toma la matriz subyacente, aplica el método apropiado y, si corresponde, devuelve una nueva matriz. Pero dado que ArrayOps no está especializado en primitivas, es lento (tan lento como siempre es el boxeo/unboxing).

WrappedArray es una antigua matriz de Java simple, pero envuelta en todos los objetos de colección de Scala. La diferencia entre él y ArrayOps es que WrappedArray devuelve otro WrappedArray - por lo menos no tiene la sobrecarga de tener que volver a ArrayOps su matriz de primitiva Java una y otra vez para cada operación. Es bueno usarlo cuando se hace mucha interoperabilidad con Java y se debe pasar en matrices antiguas Java simples, pero en el lado de Scala se deben manipular convenientemente.

ArraySeq almacena sus datos en una antigua matriz Java simple, pero ya no almacena matrices de primitivas; todo es una matriz de objetos. Esto significa que las primitivas se empacan en el camino de entrada. Eso es realmente conveniente si quiere usar las primitivas muchas veces; ya que tiene copias en caja almacenadas, solo tiene que desempaquetarlas, no guardarlas en cajas y unboxearlas en cada operación genérica.

ArrayBuffer actúa como una matriz, pero puede agregar y quitar elementos de ella. Si va a ir hasta el ArraySeq, ¿por qué no tener la flexibilidad añadida de cambiar de longitud mientras lo hace?

+0

esto debería ser parte de cada (y cualquier) documentación scala alrededor de las colecciones. +1 – Dragonborn

0

Como observó correctamente, ArraySeq tiene una API más rica, ya que se deriva de IndexedSeq (y así sucesivamente) mientras que Array es una representación directa de las matrices de Java.

La relación entre ambos se podría comparar con la relación de ArrayList y las matrices en Java.

Debido a su API, recomendaría usar el ArraySeq a menos que haya una razón específica para no hacerlo. Usando toArray(), puede convertir a una matriz en cualquier momento.

+2

¡No es así! Tienen la misma API ...] (http://www.scala-lang.org/api/current/scala/collection/mutable/ArrayLike.html) –

+0

Ah, no vi la conversión implícita –

6

De los scala-lang.org forum:

Matriz [T] - Beneficios: Nativo, rápido - Limitaciones: algunos métodos (sólo se aplican, actualización, longitud), necesita saber T en de compilación tiempo, porque Java bytecode representa (char [] diferente de int [] diferente de Object [])

ArraySeq [T] (la clase anteriormente conocida como GenericArray [T]): - Beneficios: Todavía respaldado por una matriz nativa, no es necesario saber nada de T en tiempo de compilación (nuevos ArraySeq [T] "sólo obras", incluso si no hay nada sabe sobre T), todo el conjunto de métodos SeqLike, de la SEC [T] - Limitaciones: se respaldado por un conjunto [AnyRef], independientemente de lo que T es (si T es primitivo, entonces serán encajonados elementos/unboxed en su camino en o fuera de la matriz de respaldo )


ArraySeq [Cualquier] es mucho más rápido que Matriz [Cualquier] al manejar primitivas. En cualquier código que tenga Matriz [T], donde T no es <: AnyRef, obtendrá un rendimiento más rápido de de ArraySeq.

+2

Seguramente tener eso al revés - como dice su cita, ArraySeq boxes y unboxes primitives. –

+0

@Jim - Lo mismo ocurre con 'Array [Any]', simplemente lo hace más lentamente. Para obtener el rendimiento de 'Array' debe escribirse como' Array [Int] ', o cualquier otra primitiva que estés usando. –

+0

@Kevin Pero dijo "En cualquier código tienes Array [T], donde T no es <: AnyRef, obtendrás un rendimiento más rápido de ArraySeq" ... lo cual no es cierto si T es Int. –

8

Array es una representación directa de Java de Array, y utiliza exactamente el mismo código de bytes en la JVM.

La ventaja de la matriz es que es la única tipo de colección en la JVM para no caer en el tipo de borrado, matrices también son capaces de mantener directamente primitivas sin el boxeo, esto puede hacerlas muy rápido en algunas circunstancias.

Además, obtienes el comportamiento de covarianza de la matriz averiada de Java. (Si pasa, p.un Array[Int] a alguna clase de Java que se puede asignar a una variable de tipo Array[Object] que luego lanzar una ArrayStoreException en tratar de añadir nada que no sea una int.)

ArraySeq se usa raramente hoy en día, más de un histórico artefacto de versiones anteriores de Scala que trataba las matrices de forma diferente. Teniendo en cuenta que debes lidiar con el boxeo de todos modos, es casi seguro que encontrarás otro tipo de colección que se ajuste mejor a tus necesidades.

De lo contrario ... Las matrices tienen exactamente la misma API que ArraySeq, gracias a una conversión implícita de Array a ArrayOps.

A menos que tenga una necesidad específica de las propiedades únicas de las matrices, intente evitarlas también. Consulte This Talk at around 19:30 o This Article para tener una idea del tipo de problemas que Arrays puede presentar.

Después de ver el video, es interesante observar que utiliza Scala Seq para varargs :)