Jaka jest różnica między kolekcjami.unmodifableset () i ImmutableSet of Guava?

JavaDoc z ImmutableSet mówi:

W przeciwieństwie do Collections.unmodifiableSet, która jest widokiem oddzielnej kolekcji, która może nadal się zmieniać, instancja tej klasy zawiera swoje prywatne dane i nigdy się nie zmieni. Ta klasa jest wygodna dla publicznych statycznych zestawów końcowych ("stałe zestawy"), a także pozwala na łatwe tworzenie" defensywnej kopii " zestawu dostarczonego klasie przez wywołującego.

Ale {[1] } nadal przechowuje odniesienia do elementów, nie mogłem rozgryźć różnica do Collections.unmodifiableSet(). Próbka:

StringBuffer s=new StringBuffer("a");
ImmutableSet<StringBuffer> set= ImmutableSet.of(s);
s.append("b");//s is "ab", s is still changed here!
Czy ktoś mógłby to wyjaśnić?
Author: ROMANIA_engineer, 2011-04-10

4 answers

Rozważ to:

Set<String> x = new HashSet<String>();
x.add("foo");

ImmutableSet<String> guava = ImmutableSet.copyOf(x);
Set<String> builtIn = Collections.unmodifiableSet(x);

x.add("bar");
System.out.println(guava.size()); // Prints 1
System.out.println(builtIn.size()); // Prints 2

Innymi słowy, ImmutableSet jest niezmienna pomimo tego, z jakiej kolekcji jest zbudowana, ponieważ tworzy kopię. Collections.unmodifiableSet zapobiega bezpośredniej zmianie kolekcjizwróconej , ale nadal jest to Widok na potencjalnie zmieniającym się zestawie podkładów.

Zauważ, że jeśli zaczniesz zmieniać zawartość obiektów określonych przez dowolny zestaw, wszystkie zakłady i tak są wyłączone. Nie rób tego. Rzeczywiście, rzadko jest dobrym pomysłem, aby stworzyć ustawia się za pomocą zmiennego typu elementu. (Tak samo mapuje się używając zmiennego typu klucza.)

 90
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-10 11:23:07

Poza różnicą behawioralną, o której wspomina Jon, ważną różnicą między ImmutableSet a Set stworzonymi przez Collections.unmodifiableSet jest to, że ImmutableSetjest typem . Możesz je przekazać i mieć pewność, że zestaw jest niezmienny, używając ImmutableSet zamiast Set w całym kodzie. Z Collections.unmodifiableSet, zwracanym typem jest po prostu Set... więc jest tylko jasne, że zestaw jest niemodyfikowalny w punkcie, w którym został utworzony, chyba że dodasz Javadoc wszędzie, gdzie przechodzisz, że Set mówiąc " ten zestaw jest niezmodyfikowany".

 21
Author: ColinD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-10 16:27:42

Kevin Bourrillion (guava lead developer) porównuje niezmienne / niezmodyfikowane kolekcje w tej prezentacji . Chociaż prezentacja ma dwa lata i skupia się na "kolekcjach Google" (które są obecnie podczęścią Guava), jest to bardzo ciekawa prezentacja . API może się zmieniać tu i ówdzie (Google Collections API był w wersji Beta w tym czasie), ale koncepcje stojące za Google Collections / Guava są nadal aktualne.

Możesz być również zainteresowany to drugie pytanie ( Jaka jest różnica między Google ImmutableList i kolekcje.unmodifiableList () ).

 10
Author: Etienne Neveu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:18

Różnica między dwoma Nie podanymi w innych odpowiedziach jest taka, że ImmutableSet nie pozwala null wartości, jak opisano w Javadoc

Wysokowydajny, niezmienny Zestaw z niezawodną, określoną przez użytkownika kolejnością iteracji. Nie dopuszcza elementów null.

(to samo ograniczenie dotyczy wartości we wszystkich niezmiennych zbiorach Guava.)

Na przykład:

ImmutableSet.of(null);
ImmutableSet.builder().add("Hi").add(null); // Fails in the Builder.
ImmutableSet.copyOf(Arrays.asList("Hi", null));

Wszystkie z nich zawodzą podczas pracy. Natomiast:

Collections.unmodifiableSet(new HashSet<>(Arrays.asList("Hi", null)));
To jest w porządku.
 3
Author: Andy Turner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-22 07:40:52