concatenate java scala scala-collections

java - concatenate - Práctica estándar de la colección Scala



scala mutable collections (4)

¿Por qué se definen List y Seq en el paquete scala y no en scala.collection (aunque las implementaciones de Seq están en los subpaquetes de recopilación)?

Debido a que se consideran tan útiles en general, se importan automáticamente en todos los programas a través de sinónimos en scala.Predef.

¿Cuál es el mecanismo estándar para inicializar una colección y luego congelarla (que en Java se logra envolviendo de forma no modificable)?

Java no tiene un mecanismo para congelar una colección. Solo tiene un modismo para envolver la colección (aún modificable) en un contenedor que arroja una excepción. La expresión apropiada en Scala es copiar una colección mutable en una inmutable, probablemente usando: _ *

¿Por qué algunos tipos de colecciones (por ejemplo, MultiMap) solo se definen como mutables? (No hay un MultiMap inmutable)?

El equipo / comunidad simplemente no ha llegado aún. La rama 2.7 vio un montón de adiciones y se espera que 2.8 tenga mucho más.

Lo siguiente parece poco manejable debido a las declaraciones del paquete completo impuesto:

Scala permite importar alias, por lo que siempre es menos detallado que Java en este aspecto (consulte, por ejemplo, java.util.Date y java.sql.Date, utilizando ambas fuerzas para estar completamente calificado)

import scala.collection.{Set => ISet} import scala.collection.mutable.{Set => MSet} class MyScala { var mySet: ISet[String] = null def init(): Unit = { val s = MSet.empty[String] s + "Hello" s + "World" mySet = Set(s : _ *) } }

Por supuesto, simplemente escribirías init como def init() { mySet = Set("Hello", "World")} y guardarías todos los problemas o mejor aún solo lo var mySet : ISet[String] = Set("Hello", "World") en el constructor var mySet : ISet[String] = Set("Hello", "World")

Viniendo de un fondo de Java , estoy acostumbrado a la práctica común de tratar con colecciones: obviamente habría excepciones, pero por lo general el código se vería así:

public class MyClass { private Set<String> mySet; public void init() { Set<String> s = new LinkedHashSet<String>(); s.add("Hello"); s.add("World"); mySet = Collections.unmodifiableSet(s); } }

Debo confesar que estoy un poco aturdido por la gran cantidad de opciones en Scala. Ahi esta:

  • scala.List (y Seq )
  • scala.collections.Set (y Map )
  • scala.collection.immutable.Set (y Map , Stack pero no List )
  • scala.collection.mutable.Set (y Map , Buffer pero no List )
  • scala.collection.jcl

¡Así que preguntas!

  1. ¿Por qué se definen List y Seq en el paquete scala y no en scala.collection (aunque las implementaciones de Seq están en los scala.collection recopilación)?
  2. ¿Cuál es el mecanismo estándar para inicializar una colección y luego congelarla (que en Java se logra envolviendo de forma unmodifiable )?
  3. ¿Por qué algunos tipos de colecciones (por ejemplo, MultiMap ) solo se definen como mutables? (No hay un MultiMap inmutable)?

He leído la excelente serie de Daniel Spiewak sobre las colecciones scala y todavía estoy desconcertado por cómo uno realmente las usaría en la práctica. Lo siguiente parece poco manejable debido a las declaraciones del paquete completo impuesto:

class MyScala { var mySet: scala.collection.Set[String] = null def init(): Unit = { val s = scala.collection.mutable.Set.empty[String] s + "Hello" s + "World" mySet = scala.collection.immutable.Set(s : _ *) } }

Aunque podría decirse que esto es más correcto que la versión de Java ya que la colección inmutable no puede cambiar (como en el caso de Java, donde la colección subyacente podría ser alterada debajo del contenedor unmodifiable )


Las colecciones mutables son útiles ocasionalmente (aunque estoy de acuerdo en que siempre debes mirar primero las inmutables). Si los uso, tiendo a escribir

import scala.collection.mutable

en la parte superior del archivo, y (por ejemplo):

val cache = new mutable.HashMap[String, Int]

en mi código Significa que solo tiene que escribir "mutable.HashMap", no scala.collection.mutable.HashMap ". Como comentarista mencionado anteriormente, podría reasignar el nombre en la importación (por ejemplo, "importar scala.collection.mutable. {HashMap => MMap}"), pero:

  1. Prefiero no manipular los nombres, para que quede más claro qué clases estoy usando, y
  2. Yo uso ''mutable'' rara vez lo suficiente que tener "mutable.ClassName" en mi fuente no es una carga excesiva.

(Además, puedo hacerme eco del comentario ''evitar los nulos'' también. Hace que el código sea mucho más robusto y comprensible. Encuentro que ni siquiera tengo que usar la opción tanto como cabría esperar).


Tenga en cuenta que puede haber algunas incoherencias en la API de colecciones de Scala en la versión actual; para Scala 2.8 (que se lanzará más adelante en 2009), la API de colecciones se está revisando para que sea más coherente y más flexible.

Vea este artículo en el sitio web de Scala: http://www.scala-lang.org/node/2060

Para agregar al ejemplo de Tristan Juricek con un lateBoundSet: Scala tiene un mecanismo incorporado para la inicialización lenta, usando la palabra clave "perezosa":

class MyClass { lazy val mySet = Set("Hello", "World") }

Al hacer esto, mySet se inicializará en el primer uso, en lugar de hacerlo de forma inmediata al crear una nueva instancia de MyClass.


Un par de pensamientos aleatorios:

  1. Nunca uso null , utilizo Option , que arrojaría un error decente. Esta práctica ha eliminado NullPointerException oportunidades de NullPointerException y obliga a las personas a escribir errores decentes.
  2. Intenta evitar mirar las cosas "mutables" a menos que realmente lo necesites.

Por lo tanto, mi versión básica de tu ejemplo scala, donde tienes que inicializar el conjunto más tarde, es

class MyScala { private var lateBoundSet:Option[ Set[ String ] ] = None def mySet = lateBoundSet.getOrElse( error("You didn''t call init!") ) def init { lateBoundSet = Some( Set( "Hello", "World" ) ) } }

He estado llorando recientemente en la oficina. "null es malvado"