Неизменяемые коллекции Java - PullRequest
107 голосов
/ 10 октября 2011

Из Документация по Java 1.6 Collection Framework :

Коллекции, которые не поддерживают какие-либо операции модификации (такие как add, remove и clear), называются неизменяемыми . [...] Коллекции, которые дополнительно гарантируют, что никакие изменения в объекте Коллекции никогда не будут видны, называются immutable .

Второй критерий меня немного смущает. Учитывая, что первая коллекция не подлежит изменению, и при условии, что исходная ссылка на коллекцию была удалена, каковы изменения, которые упоминаются во второй строке? Относится ли это к изменениям в элементах, содержащихся в коллекции, то есть к состоянию элементов?

Второй вопрос:
Для того чтобы коллекция была неизменной, как можно обеспечить предоставление указанных дополнительных гарантий? Если состояние элемента в коллекции обновляется потоком, достаточно ли для неизменности того, что эти обновления в состоянии не видны в потоке, содержащем неизменную коллекцию?

Для того чтобы коллекция была неизменной, как можно обеспечить предоставление указанных дополнительных гарантий?

Ответы [ 6 ]

146 голосов
/ 10 октября 2011

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

Неизменяемые коллекции не могут быть изменены вообще - они не переносят другую коллекцию - у них есть свои собственные элементы.

Вот цитата из гуавы ImmutableList

В отличие от Collections.unmodifiableList(java.util.List<? extends T>), который представляет собой отдельную коллекцию, которая все еще может измениться, экземпляр ImmutableList содержит свои личные данные и никогда не изменится.

Таким образом, для извлечения неизменяемой коллекции из изменяемой коллекции необходимо скопировать ее элементы в новую коллекцию и запретить все операции.

84 голосов
/ 10 октября 2011

Разница в том, что вы не можете иметь ссылку на неизменяемую коллекцию, которая допускает изменения.Немодифицируемые коллекции не могут быть изменены через эту ссылку , но некоторые другие объекты могут указывать на те же данные, с помощью которых они могут быть изменены.

например

List<String> strings = new ArrayList<String>();
List<String> unmodifiable = Collections.unmodifiableList(strings);
unmodifiable.add("New string"); // will fail at runtime
strings.add("Aha!"); // will succeed
System.out.println(unmodifiable);
19 голосов
/ 10 октября 2011
Collection<String> c1 = new ArrayList<String>();
c1.add("foo");
Collection<String> c2 = Collections.unmodifiableList(c1);

c1 является изменяемым (т.е. ни неизменяемым , ни неизменным ).
c2 является неизменяемым : оно не может быть изменено само по себе, но если позже я изменю c1, тогда это изменение будет видно в c2.

Это потому, что c2 - это просто оболочка вокруг c1, а не независимая копия. Guava предоставляет интерфейс ImmutableList и некоторые реализации. Они работают, фактически создавая копию входных данных (если входные данные не являются самостоятельной неизменной коллекцией).

Относительно вашего второго вопроса:

Изменчивость / неизменность коллекции не зависит от изменчивости / неизменности содержащихся в ней объектов. Модификация объекта, содержащегося в коллекции, не считается «модификацией коллекции» для этого описания. Конечно, если вам нужна неизменяемая коллекция, вы обычно также хотите, чтобы она содержала неизменяемые объекты.

14 голосов
/ 13 марта 2017

Теперь java 9 имеет фабричные методы для неизменного списка, набора, карты и карты. Вход.

В Java SE 8 и более ранних версиях мы можем использовать служебные методы класса Collections, такие как unmodifiableXXXсоздавать объекты неизменной коллекции.

Однако эти методы Collections.unmodifiableXXX очень утомительны и многословны.Чтобы преодолеть эти недостатки, корпорация Oracle добавила несколько служебных методов в интерфейсы List, Set и Map.

Теперь в java 9: ​​- В интерфейсах List и Set есть методы «of ()»создать пустой или непустой неизменяемый список или объекты Set, как показано ниже:

Пример пустого списка

List immutableList = List.of();

Пример непустого списка

List immutableList = List.of("one","two","three");
6 голосов
/ 10 октября 2011

Я считаю, что суть в том, что даже если коллекция не изменяема, это не гарантирует, что она не может измениться.Возьмите, например, коллекцию, которая выселяет элементы, если они слишком стары.Unmodifiable просто означает, что объект, содержащий ссылку, не может ее изменить, а не то, что он не может измениться.Настоящим примером этого является Collections.unmodifiableList метод.Возвращает неизменяемое представление списка.Ссылка List, которая была передана в этот метод, все еще может быть изменена, поэтому список может быть изменен любым держателем переданной ссылки.Это может привести к ConcurrentModificationExceptions и другим плохим вещам.

Неизменяемые, означают, что коллекция никоим образом не может быть изменена.

Второй вопрос: Неизменяемая коллекция не означает, что объекты, содержащиеся вколлекция не изменится, просто эта коллекция не изменится по количеству и составу объектов, которые она содержит.Другими словами, список ссылок коллекции не изменится.Это не означает, что внутренности объекта, на который ссылаются, не могут измениться.

0 голосов
/ 04 ноября 2015

Pure4J поддерживает то, что вам нужно, двумя способами.

Во-первых, он предоставляет аннотацию @ImmutableValue, так что вы можете комментировать класс, чтобы сказать, что он неизменен.Существует плагин maven, позволяющий вам проверить, что ваш код на самом деле неизменен (использование final и т. Д.).

Во-вторых, он предоставляет постоянные коллекции из Clojure (с добавленными обобщениями) и обеспечивает неизменность элементов, добавляемых в коллекции.Производительность этих, видимо, довольно хорошая.Все коллекции являются неизменяемыми, но реализуют интерфейсы коллекций Java (и обобщения) для проверки.Мутация возвращает новые коллекции.

Отказ от ответственности: я разработчик этого

...