2016-09-21 10 views
0

Warum ist es, dass die folgenden ohne Ausnahme ausgeführt wird:Mutable Karten mit Objektschlüssel

import scala.collection.mutable 

class Label(val name: String) { 
    override def toString = s"Label($name)" 
} 

object Main extends App { 
    var map = mutable.Map[Label, Int]() 
    val ab = new Label("AB") 
    map += ab -> 1 
    println(map(ab)) 
} 

Während das Folgende ergeben ein NoSuchElementException:

import scala.collection.mutable 

class Label(val name: String) { 
    override def toString = s"Label($name)" 
} 

object Main extends App { 
    var map = mutable.Map[Label, Int]() 
    map += new Label("AB") -> 1 
    println(map(new Label("AB"))) 
} 

Ich habe es nicht gelungen, eine Lösung zu finden, um dies, aber ich glaube, dass es sich auf einen Unterschied zwischen Gleichheit und Identität in Scala beziehen muss.

+0

Duplikat von [wie-ist-Schlüssel-Äquivalenz-definiert-wann-verwenden-Scalas-hashmap] (http://stackoverflow.com/questions/10805570/how-is-key-equivalence-defined-when-using -scalas-hashmap) – Samar

Antwort

0

Gleichheit und Identität in Scala sind wie in Java. Standardmäßig sind zwei Objekte nur dann identisch, wenn sie identisch sind. Eine Klasse muss equals und hashCode überschreiben, damit zwei verschiedene Objekte in Hashing-Daten als gleichwertig behandelt werden. Wenn diese Methoden nicht überschrieben werden, sind zwei beliebige Objekte nicht "gleich" und werden nicht als Hash-Schlüssel verwendet.

Der Hauptunterschied zwischen Java und Scala ist, dass der Operator == Gleichheit testet, d. H. Die equals Methode verwendet, während in Java == Identität testet. (Um die Identität in Scala zu testen, verwenden Sie den Operator eq.)

In Ihrem zweiten Codefragment ergibt also jede Auswertung von new Label("AB") ein eindeutiges, nicht relevantes Objekt. Das Nachschlagen auf das Ergebnis der zweiten Auswertung kann nicht zur ersten ausgewertet werden.

In Scala viel mehr als Java jedoch ist die übliche Praxis, unveränderliche Objekte zu definieren, die equals und hashCode überschreiben. Scala bietet den Begriff "Fallklassen" an, die diese Methoden unter anderem automatisch überschreiben.

Sie können Ihr zweites Code-Snippet reparieren, indem Sie das Wort case vor Ihre Klassendefinition für Label setzen.

scala> import scala.collection.mutable 
import scala.collection.mutable 

scala> case class Label(val name: String) { 
    |  override def toString = s"Label($name)" 
    | } 
defined class Label 

scala> object Main extends App { 
    |  var map = mutable.Map[Label, Int]() 
    |  map += new Label("AB") -> 1 
    |  println(map(new Label("AB"))) 
    | } 
defined object Main 

scala> Main.main(Array.empty[String]) 
1 

Beachten Sie, dass Fallklassen auch automatisch für die Klasse eines Begleitobjekt definieren, und eine apply Methode, die den Haupt-Konstruktor aufruft. Anstatt also new Label("AB") zu schreiben, wäre es konventioneller, einfach Label("AB") zu schreiben.