Z dokumentacji Java 1.6 Collection Framework :
Kolekcje, które nie obsługują żadnych operacji modyfikacji (takich jak
add
,remove
iclear
) są określane jako niemodyfikowalne . […] Kolekcje, które dodatkowo gwarantują, że żadna zmiana w obiekcie Collection nigdy nie będzie widoczna, nazywane są niezmiennymi .
Drugie kryterium trochę mnie dezorientuje. Biorąc pod uwagę, że pierwsza kolekcja jest niemodyfikowalna i przy założeniu, że oryginalne odniesienie do kolekcji zostało usunięte, jakie zmiany są wymienione w drugiej linii? Czy to odnosi się do zmian w elementach znajdujących się w kolekcji, czyli stanu elementów?
Drugie pytanie:
Aby kolekcja była niezmienna, w jaki sposób można zapewnić dodatkowe określone gwarancje? Jeśli stan elementu w kolekcji jest aktualizowany przez wątek, czy dla niezmienności wystarczy, że te aktualizacje w stanie nie są widoczne w wątku zawierającym niezmienną kolekcję?
Aby kolekcja była niezmienna, w jaki sposób można zapewnić dodatkowe określone gwarancje?
źródło
newCol = oldCol.add("element")
utworzy nową kolekcję, która jest kopią starej z 1 elementem więcej, a wszystkie odwołania dooldCol
będą nadal wskazywały na tę samą niezmienioną starą kolekcję.Odpowiedzi:
Kolekcje niemodyfikowalne to zazwyczaj widoki tylko do odczytu (opakowania) innych kolekcji. Nie możesz ich dodawać, usuwać ani czyścić, ale podstawowa kolekcja może się zmienić.
Niezmiennych kolekcji nie można w ogóle zmienić - nie zawijają one innej kolekcji - mają własne elementy.
Oto cytat z guawy
ImmutableList
Zasadniczo więc, aby uzyskać niezmienną kolekcję z mutowalnej, musisz skopiować jej elementy do nowej kolekcji i zabronić wszystkich operacji.
źródło
unmodifiableList
, kod, który otrzymuje tylko odniesienie do tej listy, nie będzie mógł jej zmodyfikować, ale każdy kod, który miał odniesienie do oryginalnej listy i mógł zmodyfikować ją przed utworzeniem opakowania, nadal będzie móc to zrobić później. Jeśli kod, który utworzył oryginalną listę, wie, co się stało z każdym odniesieniem, które kiedykolwiek do niej istniało, i wie, że żadne z nich nie wpadnie w ręce kodu, który mógłby zmodyfikować listę, to może wiedzieć, że lista nigdy nie będzie zmodyfikowany. Jeśli jednak odniesienie zostało otrzymane z zewnętrznego kodu ...unmodifiableList
ani żaden kod, który go używa, wiedzieli, czy lub jak opakowana kolekcja może się zmienić.Różnica polega na tym, że nie można mieć odwołania do niezmiennej kolekcji, która umożliwia zmiany. Kolekcje niemodyfikowalne są niemodyfikowalne poprzez to odniesienie nie mogą być , ale jakiś inny obiekt może wskazywać na te same dane, za pomocą których można je zmienić.
na przykład
źródło
c1
jest zmienny (tj. ani niemodyfikowalny, ani niezmienny ).c2
jest niezmienne : nie może być zmieniana sama, ale jeśli później zmienićc1
wtedy , że zmiany będą widoczne wc2
.Dzieje się tak, ponieważ
c2
jest po prostu opakowaniemc1
i nie jest tak naprawdę niezależną kopią. Guava zapewniaImmutableList
interfejs i niektóre implementacje. Działają one poprzez faktyczne tworzenie kopii danych wejściowych (chyba że dane wejściowe są same w sobie niezmienną kolekcją).Odnośnie drugiego pytania:
Zmienność / niezmienność kolekcji nie zależy od zmienności / niezmienności obiektów w niej zawartych. Modyfikacja obiektu zawartego w kolekcji nie liczy się jako „modyfikacja kolekcji” w tym opisie. Oczywiście, jeśli potrzebujesz niezmiennej kolekcji, zwykle chcesz, aby zawierała niezmienne obiekty.
źródło
c1
nie ucieka” nie jest kwestią wyróżnioną w dowolnym miejscu specyfikacji. Moim zdaniem, jeśli pan może korzystać ze zbiorów w sposób, który sprawia, że nie niezmienne, to należy zawsze uważają, że zakaz niezmienne.Collection.unmodifiableList()
nie może tego zagwarantować, ponieważ nie może zagwarantować, że jego argument nie ucieknie. GuawaImmutableList.of
zawsze tworzy niezmienneList
, nawet jeśli pozwolisz uciec jego argumentom.Teraz java 9 ma fabryczne metody dla Immutable List, Set, Map i Map.Entry.
W Javie SE 8 i wcześniejszych wersjach możemy używać metod narzędziowych klasy Collections, takich jak unmodifiableXXX, do tworzenia obiektów Immutable Collection.
Jednak te metody Collections.unmodifiableXXX są bardzo żmudne i rozwlekłe. Aby przezwyciężyć te niedociągnięcia, firma Oracle dodała kilka metod narzędziowych do interfejsów List, Set i Map.
Teraz w java 9: - Interfejsy List i Set mają metody „of ()” do tworzenia pustych lub niepustych obiektów Immutable List lub Set, jak pokazano poniżej:
Przykład pustej listy
Przykład niepustej listy
źródło
List.copyOf
iSet.copyOf
zostały dodane, które pozwalają na tworzenie niemodyfikowalnej kopii listy / zestawu lub zwracają daną kolekcję, jeśli jest już niemodyfikowalna, zobacz JDK-8191517Uważam, że chodzi o to, że nawet jeśli kolekcja jest niemodyfikowalna, nie gwarantuje to, że nie może się zmienić. Weźmy na przykład kolekcję, która eksmituje elementy, jeśli są zbyt stare. Niemodyfikowalność oznacza po prostu, że obiekt przechowujący odniesienie nie może go zmienić, a nie że nie może się zmienić. Prawdziwym tego przykładem jest
Collections.unmodifiableList
metoda. Zwraca niemodyfikowalny widok listy. Odwołanie List, które zostało przekazane do tej metody, jest nadal modyfikowalne, dlatego lista może być modyfikowana przez dowolnego posiadacza przekazanego odwołania. Może to spowodować wystąpienie wyjątków ConcurrentModificationExceptions i innych złych rzeczy.Niezmienne, oznaczają, że w żaden sposób nie można zmienić kolekcji.
Drugie pytanie: Niezmienna kolekcja nie oznacza, że obiekty zawarte w kolekcji nie ulegną zmianie, po prostu ta kolekcja nie zmieni się w liczbie i składzie obiektów, które posiada. Innymi słowy, lista odniesień do kolekcji nie ulegnie zmianie. Nie oznacza to, że elementy wewnętrzne obiektu, do którego się odwołujemy, nie mogą się zmienić.
źródło
unmodifiableList
zmodyfikowanej. Jeśli chcesz to zrobić, użyjImmutableList
.Pure4J wspiera to, czego szukasz, na dwa sposoby.
Po pierwsze, zapewnia
@ImmutableValue
adnotację, dzięki czemu można dodać adnotację do klasy, aby powiedzieć, że jest niezmienna. Istnieje wtyczka maven, która umożliwia sprawdzenie, czy kod faktycznie jest niezmienny (użyciefinal
itp.).Po drugie, zapewnia trwałe kolekcje z Clojure (z dodanymi rodzajami) i zapewnia, że elementy dodane do kolekcji są niezmienne. Wydajność tych jest najwyraźniej całkiem niezła. Kolekcje są niezmienne, ale zaimplementuj interfejsy kolekcji Java (i typy ogólne) do wglądu. Mutacja zwraca nowe kolekcje.
Zastrzeżenie: jestem twórcą tego
źródło