Подтвердить что ты не робот

Какая разница между Collections.unmodifiableSet() и ImmutableSet от Guava?

JavaDoc ImmutableSet говорит:

В отличие от Collections.unmodifiableSet, который является видом отдельной коллекции, которая все еще может измениться, экземпляр этого класса содержит свои личные данные и никогда не изменится. Этот класс удобен для публичных статических окончательных наборов ( "постоянные наборы" ), а также позволяет легко сделать "защитную копию" набора, предоставленного вашему классу вызывающим.

Но ImmutableSet по-прежнему сохраняет ссылку на элементы, я не мог понять разницу в Collections.unmodifiableSet(). Пример:

StringBuffer s=new StringBuffer("a");
ImmutableSet<StringBuffer> set= ImmutableSet.of(s);
s.append("b");//s is "ab", s is still changed here!

Может ли кто-нибудь объяснить это?

4b9b3361

Ответ 1

Рассмотрим это:

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

Другими словами, ImmutableSet неизменен, несмотря на то, что сборник, который он создал из потенциально изменяющегося, - потому что он создает копию. Collections.unmodifiableSet предотвращает прямое изменение возвращенной коллекции, но она все еще является представлением о потенциально изменяющемся наборе поддержки.

Обратите внимание, что если вы начнете изменять содержимое объектов, на которые ссылается любой набор, все ставки все равно. Не делай этого. В самом деле, редко возникает идея создать набор с использованием типа изменяемого элемента в первую очередь. (Ditto карты с использованием изменяемого типа ключа.)

Ответ 2

Помимо различий в поведении, которые упоминает Джон, важным отличием между ImmutableSet и Set, созданным Collections.unmodifiableSet, является то, что ImmutableSet является типом. Вы можете пройти один вокруг и оставить в ясности, что набор является неизменным, используя ImmutableSet, а не Set во всем коде. С Collections.unmodifiableSet возвращаемый тип - это просто Set... поэтому он очищает только то, что множество немодифицируется в том месте, где оно создано, если вы не добавите Javadoc всюду, где вы проходите, что Set говорит: "этот набор не поддается изменению".

Ответ 3

Кевин Бурриллион (ведущий разработчик Guava) сравнивает неизменяемые/немодифицируемые коллекции в эту презентацию. В то время как презентация - два года, и она фокусируется на "Коллекциях Google" (которая теперь является подразделением Guava), это очень интересная презентация. API, возможно, изменился здесь и там (API Google Collections API был в бета-версии в то время), но концепции Google Collections/Guava по-прежнему актуальны.

Вы также можете быть заинтересованы в этом другом вопросе SO (в чем разница между google ImmutableList и Collections.unmodifiableList()).

Ответ 4

Разница между двумя, не указанными в других ответах, заключается в том, что ImmutableSet не позволяет значения null, как описано в Javadoc

Высокопроизводительный неизменяемый набор с надежным, заданным пользователем порядком итерации. Не разрешает нулевые элементы.

(Такое же ограничение применяется к значениям во всех неизменяемых коллекциях Guava.)

Например:

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

Все они не работают во время выполнения. Напротив:

Collections.unmodifiableSet(new HashSet<>(Arrays.asList("Hi", null)));

Это нормально.