31 votes

Pratique standard de la collection Scala

Venant d'un Java fond, je suis habitué à la pratique courante de traiter avec des collections: évidemment, il y aurait des exceptions, mais généralement de code devrait ressembler à:

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);
  }
}

Je dois avouer que je suis un peu déconcerté par la pléthore d'options en Scala. Il y a:

  • scala.List (et Seq)
  • scala.collections.Set (et Map)
  • scala.collection.immutable.Set (et Map, Stack mais pas List)
  • scala.collection.mutable.Set (et Map, Buffer mais pas List)
  • scala.collection.jcl

Tellement de questions!

  1. Pourquoi sont - List et Seq défini dans le package scala et pas scala.collection (même si les implémentations de l' Seq se trouvent dans la collection de sous-paquets)?
  2. Quel est le mécanisme standard pour l'initialisation d' une collection, puis de congélation (ce qui dans le langage Java est réalisé en l'enveloppant dans un unmodifiable)?
  3. Pourquoi certains types de collection (par exemple, MultiMap) seulement défini comme muable? (Il n'est pas immuable MultiMap)?

J'ai lu Daniel Spiewak de l' excellente série sur les collections scala et je suis toujours intrigué par la façon dont on pourrait les utiliser dans la pratique. La suite semble un peu lourd en raison de la disparition forcée package complet déclarations:

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 : _ *)

  }
}

Bien que l'on peut dire que c'est plus correct que la version de Java que l'immuable collection ne peut pas changer (comme en Java cas, où la collection sous-jacente pourrait être modifiée sous l' unmodifiable wrapper)

26voto

James Iry Points 14192

Pourquoi sont-Liste et Seq définie dans le package de scala et pas de la scala.collection (même si les implémentations de Seq sont dans la collection de sous-paquets)?

Parce qu'ils sont considérés comme si utiles qu'ils sont automatiquement importés dans tous les programmes via la synonymes de scala.Predef.

Quel est le mécanisme standard pour l'initialisation d'une collection, puis de les congeler (qui en Java est réalisé en l'enveloppant dans un inmodifiable)?

Java ne dispose pas d'un mécanisme de gel d'une collection. Il ne dispose que d'un idiome pour l'emballage (qui reste modifiable) collection dans un wrapper qui lève une exception. Le bon langage dans le Scala est de copier une mutable collection dans un immuable - probablement à l'aide de :_*

Pourquoi certains types de collection (par exemple, MultiMap) défini comme muable? (Il n'est pas immuable MultiMap)?

L'équipe/communauté n'a pas eu là encore. La branche 2.7 vu un tas d'ajouts et de 2,8 devrait avoir un tas plus.

La suite semble un peu lourd en raison de la disparition forcée package complet déclarations:

Scala permet d'importer des alias de sorte qu'il est toujours moins verbeux que Java à cet égard (voir, par exemple, java.util.Date et java.sql.Date - à l'aide de deux forces, l'une pour être pleinement qualifié)

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 : _ *)
  }
}

Bien sûr, vous auriez vraiment juste écrire init comme def init() { mySet = Set("Hello", "World")} et enregistrer toutes les difficultés ou, mieux encore, il suffit de le mettre dans le constructeur var mySet : ISet[String] = Set("Hello", "World")

7voto

andrewf Points 329

Mutable collections sont utiles à l'occasion (si je suis d'accord qu'il faut toujours regarder à l'immuable d'abord). Si leur utilisation, j'ai tendance à écrire

import scala.collection.mutable

en haut du fichier, et (par exemple):

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

dans mon code. Cela signifie que vous n'avez qu'à écrire "mutables.HashMap", pas de la scala.collection.mutable.HashMap". Comme le commentateur ci-dessus mentionnés, vous pouvez reconfigurer le nom de l'importation (par exemple, "l'importation de la scala.collection.mutable.{HashMap => MMap}"), mais:

  1. Je préfère ne pas marquer les noms, de sorte que c'est plus clair ce que les classes que j'utilise, et
  2. J'utilise "mutable' rarement assez que d'avoir des "mutables.ClassName" dans ma source n'est pas un fardeau excessif.

(Aussi, puis-je reprendre le " éviter des valeurs null,' commentaire trop. Il rend le code beaucoup plus robuste et compréhensible. Je trouve que je n'ai même pas à utiliser l'Option comme beaucoup comme vous pouvez vous attendre non plus.)

4voto

Tristan Juricek Points 1362

Un couple aléatoire de pensées:

  1. Je n'ai jamais utiliser null,- je utiliser Option, qui serait alors de jeter un décent erreur. Cette pratique a réussi à se débarrasser d'une tonne NullPointerException des occasions, et oblige les gens à écrire décent erreurs.
  2. Essayez d'éviter de regarder dans le "mutable" choses " à moins que vous vraiment besoin.

Donc, ma base de prendre sur votre scala exemple, où vous devez initialiser le jeu plus tard, est

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" ) )
  }
}

J'ai été sur une larme récemment autour de l'office. "null est mal!"

3voto

Jesper Points 65733

Notez qu'il peut y avoir quelques incohérences dans le Scala collections de l'API dans la version actuelle; pour Scala 2.8 (pour être publié plus tard en 2009), les collections de l'API est en cours de révision afin de la rendre plus cohérente et plus souple.

Voir cet article sur la Scala site web: http://www.scala-lang.org/node/2060

Pour ajouter à Tristan Juricek l'exemple avec un lateBoundSet: Scala dispose d'un mécanisme intégré pour l'initialisation, à l'aide de la "paresseux" mot-clé:

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

En faisant cela, mySet sera initialisé lors de la première utilisation, au lieu d'immédiatement lors de la création d'une nouvelle instance de Maclasse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X