Aus der Java 1.6 Collection Framework-Dokumentation :
Kollektionen , die (wie etwa keine Änderungsoperationen unterstützen
add
,remove
undclear
) , werden als nicht änderbar . [...] Sammlungen, die zusätzlich garantieren, dass keine Änderung des Sammlungsobjekts jemals sichtbar wird, werden als unveränderlich bezeichnet .
Das zweite Kriterium verwirrt mich ein bisschen. Welche Änderungen werden in der zweiten Zeile erwähnt, da die erste Sammlung nicht geändert werden kann und vorausgesetzt, dass die ursprüngliche Sammlungsreferenz entfernt wurde? Bezieht es sich auf die Änderungen in den Elementen in der Sammlung, dh auf den Status der Elemente?
Zweite Frage:
Damit eine Sammlung unveränderlich ist, wie werden die angegebenen zusätzlichen Garantien bereitgestellt? Wenn der Status eines Elements in der Sammlung von einem Thread aktualisiert wird, reicht es für die Unveränderlichkeit aus, dass diese Aktualisierungen im Status auf dem Thread, der die unveränderliche Sammlung enthält, nicht sichtbar sind?
Wie geht man vor, um eine unveränderliche Sammlung unveränderlich zu machen?
quelle
newCol = oldCol.add("element")
wird eine neue Sammlung erstellt, die eine Kopie der alten mit einem weiteren Element ist, und alle Verweise auf dieoldCol
werden weiterhin auf dieselbe unveränderte alte Sammlung verweisen.Antworten:
Nicht modifizierbare Sammlungen sind normalerweise schreibgeschützte Ansichten (Wrapper) anderer Sammlungen. Sie können sie nicht hinzufügen, entfernen oder löschen, aber die zugrunde liegende Sammlung kann sich ändern.
Unveränderliche Sammlungen können überhaupt nicht geändert werden - sie verpacken keine andere Sammlung - sie haben ihre eigenen Elemente.
Hier ist ein Zitat von Guaven
ImmutableList
Um eine unveränderliche Sammlung aus einer veränderlichen Sammlung herauszuholen, müssen Sie ihre Elemente in die neue Sammlung kopieren und alle Vorgänge nicht zulassen.
quelle
unmodifiableList
, kann Code, der nur einen Verweis auf diese Liste erhält, diese nicht ändern, aber jeder Code, der einen Verweis auf die ursprüngliche Liste hatte und diesen vor dem Erstellen des Wrappers ändern konnte, wird weiterhin geändert in der Lage sein, dies später zu tun. Wenn der Code, der die ursprüngliche Liste erstellt hat, weiß, was mit jeder Referenz passiert ist, die jemals existiert hat, und weiß, dass keiner von ihnen in die Hände von Code fällt, der die Liste ändern könnte, kann er wissen, dass die Liste niemals sein wird geändert. Wenn die Referenz jedoch von außerhalb des Codes empfangen wurde ...unmodifiableList
Code, der ihn verwendet, zu wissen, ob oder wie sich die umschlossene Sammlung ändern könnte.Der Unterschied besteht darin, dass Sie keinen Verweis auf eine unveränderliche Sammlung haben können, die Änderungen zulässt. Nicht modifizierbare Sammlungen können durch diese Referenz nicht modifiziert werden , aber ein anderes Objekt kann auf dieselben Daten verweisen, über die es geändert werden kann.
z.B
quelle
c1
ist veränderlich (dh weder unveränderlich noch unveränderlich ).c2
ist nicht änderbar : es selbst nicht, verändert, aber wenn ich später ändernc1
dann , dass wird sich ändern in sichtbar seinc2
.Dies liegt daran, dass
c2
es sich lediglich um einen Wrapper handeltc1
und nicht wirklich um eine unabhängige Kopie. Guava bietet dieImmutableList
Schnittstelle und einige Implementierungen. Diese arbeiten, indem sie tatsächlich eine Kopie der Eingabe erstellen (es sei denn, die Eingabe ist eine unveränderliche Sammlung für sich).Zu Ihrer zweiten Frage:
Die Veränderbarkeit / Unveränderlichkeit einer Sammlung hängt nicht von der Veränderlichkeit / Unveränderlichkeit der darin enthaltenen Objekte ab. Das Ändern eines in einer Sammlung enthaltenen Objekts gilt für diese Beschreibung nicht als "Änderung der Sammlung". Wenn Sie eine unveränderliche Sammlung benötigen, möchten Sie normalerweise auch, dass sie unveränderliche Objekte enthält.
quelle
c1
nicht entkommen" ist keine Überlegung, die irgendwo in der Spezifikation unterschieden wird. Wenn Sie die Sammlung meiner Meinung nach so verwenden können , dass sie nicht unveränderlich ist, sollten Sie sie meiner Meinung nach immer als nicht unveränderlich betrachten.Collection.unmodifiableList()
kann das nicht garantieren, weil es nicht garantieren kann, dass sein Argument nicht entgeht. Guave erzeugtImmutableList.of
immer eine unveränderlicheList
, auch wenn Sie ihre Argumente entkommen lassen.Jetzt verfügt Java 9 über Factory-Methoden für unveränderliche Listen, Mengen, Karten und Map.Entry.
In Java SE 8 und früheren Versionen können wir Dienstprogramme der Collections-Klasse wie unmodizableXXX verwenden, um unveränderliche Collection-Objekte zu erstellen.
Diese Collections.unmodizableXXX-Methoden sind jedoch sehr langwierig und ausführlich. Um diese Mängel zu beheben, hat Oracle Corp. den Schnittstellen List, Set und Map einige Dienstprogrammmethoden hinzugefügt.
Jetzt in Java 9: - List- und Set-Schnittstellen verfügen über "of ()" - Methoden, um eine leere oder nicht leere Immutable List oder Set-Objekte zu erstellen, wie unten gezeigt:
Beispiel für eine leere Liste
Beispiel für eine nicht leere Liste
quelle
List.copyOf
undSet.copyOf
wurden hinzugefügt, die es ermöglichen, eine nicht veränderbare Kopie einer Liste / eines Satzes zu erstellen oder die angegebene Sammlung zurückzugeben, wenn sie bereits nicht veränderbar ist, siehe JDK-8191517Ich glaube, der Punkt hier ist, dass selbst wenn eine Sammlung nicht modifizierbar ist, dies nicht sicherstellt, dass sie sich nicht ändern kann. Nehmen Sie zum Beispiel eine Sammlung, die Elemente entfernt, wenn sie zu alt sind. Nicht modifizierbar bedeutet nur, dass das Objekt, das die Referenz enthält, diese nicht ändern kann, nicht, dass es sich nicht ändern kann. Ein wahres Beispiel hierfür ist die
Collections.unmodifiableList
Methode. Es wird eine nicht veränderbare Ansicht einer Liste zurückgegeben. Die an diese Methode übergebene Listenreferenz kann weiterhin geändert werden, sodass die Liste von jedem Inhaber der übergebenen Referenz geändert werden kann. Dies kann zu ConcurrentModificationExceptions und anderen schlechten Dingen führen.Unveränderlich bedeutet, dass die Sammlung in keiner Weise geändert werden kann.
Zweite Frage: Eine unveränderliche Sammlung bedeutet nicht, dass sich die in der Sammlung enthaltenen Objekte nicht ändern, sondern dass sich die Anzahl und Zusammensetzung der darin enthaltenen Objekte in dieser Sammlung nicht ändert. Mit anderen Worten, die Referenzliste der Sammlung ändert sich nicht. Dies bedeutet nicht, dass sich die Interna des Objekts, auf das verwiesen wird, nicht ändern können.
quelle
unmodifiableList
Modified übergeben wird. Wenn Sie dies tun möchten, verwenden SieImmutableList
.Pure4J unterstützt das, wonach Sie suchen , auf zwei Arten.
Erstens enthält es eine
@ImmutableValue
Anmerkung, sodass Sie eine Klasse mit Anmerkungen versehen können, um zu sagen, dass sie unveränderlich ist. Es gibt ein Maven-Plugin, mit dem Sie überprüfen können, ob Ihr Code tatsächlich unveränderlich ist (Verwendung vonfinal
usw.).Zweitens werden die persistenten Sammlungen von Clojure (mit zusätzlichen Generika) bereitgestellt und sichergestellt, dass die den Sammlungen hinzugefügten Elemente unveränderlich sind. Die Leistung dieser ist anscheinend ziemlich gut. Sammlungen sind alle unveränderlich, implementieren jedoch Java-Sammlungsschnittstellen (und Generika) zur Überprüfung. Mutation gibt neue Sammlungen zurück.
Haftungsausschluss: Ich bin der Entwickler davon
quelle