Java неизменяемые коллекции

От Документация по сборке Java 1.6 Framework:

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

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

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

Изменить: (выделение фокуса второго вопроса):

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

Ответ 1

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

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

Здесь цитата из guava ImmutableList

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

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

Ответ 2

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

например.

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);

Ответ 3

Collection<String> c1 = new ArrayList<String>();
c1.add("foo");
Collection<String> c2 = Collections.unmodifiableList(c1);

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

Теперь в java 9: ​​- Интерфейсы "Список" и "Набор" имеют методы "()" для создания пустого или без пустого Неизменяемого списка или набора объектов, как показано ниже:

Пример с пустым списком

List immutableList = List.of();

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

List immutableList = List.of("one","two","three");

Ответ 6

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

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

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

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