Из документации Java 1.6 Collection Framework :
Коллекции, которые не поддерживают какие-либо операции модификации (например
add
,remove
иclear
), называются неизменяемыми . [...] Коллекции, которые дополнительно гарантируют, что никакие изменения в объекте Collection никогда не будут видны, называются неизменяемыми .
Второй критерий меня немного смущает. Учитывая, что первая коллекция не может быть изменена, и если исходная ссылка на коллекцию удалена, какие изменения упоминаются во второй строке? Относится ли это к изменениям в элементах, содержащихся в коллекции, то есть к состоянию элементов?
Второй вопрос:
чтобы коллекция была неизменной, как можно предоставить указанные дополнительные гарантии? Если состояние элемента в коллекции обновляется потоком, достаточно ли для неизменности, чтобы эти обновления в состоянии не были видны в потоке, содержащем неизменяемую коллекцию?
Чтобы коллекция была неизменной, как можно предоставить указанные дополнительные гарантии?
источник
newCol = oldCol.add("element")
будет создана новая коллекция, которая является копией старой с еще одним элементом, и все ссылки на нее по-oldCol
прежнему будут указывать на ту же неизменную старую коллекцию.Ответы:
Неизменяемые коллекции обычно представляют собой доступные только для чтения представления (оболочки) других коллекций. Вы не можете добавлять, удалять или очищать их, но основная коллекция может измениться.
Неизменяемые коллекции вообще нельзя изменить - они не обертывают другую коллекцию - у них есть свои собственные элементы.
Вот цитата из гуавы
ImmutableList
Итак, в основном, чтобы получить неизменяемую коллекцию из изменяемой, вы должны скопировать ее элементы в новую коллекцию и запретить все операции.
источник
unmodifiableList
, код, который получает только ссылку на этот список, не сможет его изменить, но любой код, который имел ссылку на исходный список и мог изменить его до создания оболочки, по-прежнему будет иметь возможность сделать это позже. Если код, создавший исходный список, знает, что произошло с каждой ссылкой, которая когда-либо существовала в нем, и знает, что ни одна из них не попадет в руки кода, который может изменить список, тогда он может знать, что список никогда не будет изменен. Однако, если ссылка была получена из внешнего кода ...unmodifiableList
, ни для какого-либо кода, который его использует, узнать, может ли и как измениться обернутая коллекция.Разница в том, что у вас не может быть ссылки на неизменяемую коллекцию, которая допускает изменения. Неизменяемые коллекции нельзя изменить с помощью этой ссылки , но какой-либо другой объект может указывать на те же данные, с помощью которых он может быть изменен.
например
источник
c1
является изменяемым (т.е. ни неизменным, ни неизменным ).c2
является неизменяемым : он не может быть изменен сам, но если позже я изменитьc1
то , что изменения будут видны вc2
.Это потому, что
c2
это просто оболочка,c1
а не независимая копия. Guava предоставляетImmutableList
интерфейс и некоторые реализации. Они работают, фактически создавая копию ввода (если только ввод не является неизменяемой коллекцией).По поводу вашего второго вопроса:
Изменяемость / неизменность коллекции не зависит от изменчивости / неизменности содержащихся в ней объектов. Изменение объекта, содержащегося в коллекции, не считается «модификацией коллекции» для этого описания. Конечно, если вам нужна неизменяемая коллекция, вы также обычно хотите, чтобы она содержала неизменяемые объекты.
источник
c1
не избежать» - это нигде в спецификации не выделяется. На мой взгляд, если вы можете использовать коллекцию таким образом, чтобы сделать ее неизменяемой, то вы всегда должны считать ее неизменной.Collection.unmodifiableList()
не может этого гарантировать, потому что не может гарантировать, что его аргумент не исчезнет. ГуаваImmutableList.of
всегда создает неизменяемый объектList
, даже если вы позволите его аргументам ускользнуть.Теперь в java 9 есть фабричные методы для неизменяемого списка, набора, карты и Map.Entry.
В Java SE 8 и более ранних версиях мы можем использовать служебные методы класса Collections, такие как unmodifiableXXX, для создания объектов Immutable Collection.
Однако эти методы Collections.unmodifiableXXX очень утомительны и многословны. Чтобы преодолеть эти недостатки, корпорация Oracle добавила несколько служебных методов в интерфейсы List, Set и Map.
Теперь в java 9: - Интерфейсы List и Set имеют методы «of ()» для создания пустых или непустых объектов Immutable List или Set, как показано ниже:
Пример пустого списка
Пример непустого списка
источник
List.copyOf
иSet.copyOf
были добавлены, которые позволяют создавать неизменяемую копию списка / набора или возвращать данную коллекцию, если она уже не подлежитЯ считаю, что суть здесь в том, что даже если коллекция не может быть изменена, это не гарантирует, что она не может измениться. Возьмем, к примеру, коллекцию, которая удаляет элементы, если они слишком старые. Неизменяемость просто означает, что объект, содержащий ссылку, не может ее изменить, а не то, что он не может измениться. Истинный пример этого -
Collections.unmodifiableList
метод. Он возвращает неизменяемое представление списка. Ссылка на список, переданная в этот метод, по-прежнему может быть изменена, поэтому список может быть изменен любым владельцем переданной ссылки. Это может привести к ConcurrentModificationExceptions и другим неприятным ситуациям.Неизменяемые, означают, что коллекцию никак нельзя изменить.
Второй вопрос: неизменяемая коллекция не означает, что объекты, содержащиеся в коллекции, не изменятся, просто эта коллекция не изменится в количестве и составе объектов, которые она содержит. Другими словами, список литературы коллекции не изменится. Это не означает, что внутренняя часть объекта, на который имеется ссылка, не может измениться.
источник
unmodifiableList
измененную. Если вы хотите это сделать, используйтеImmutableList
.Pure4J поддерживает то, что вам нужно, двумя способами.
Во-первых, он предоставляет
@ImmutableValue
аннотацию, так что вы можете аннотировать класс, чтобы сказать, что он неизменяемый. Существует плагин maven, который позволяет вам проверить, что ваш код действительно неизменен (использованиеfinal
и т. Д.).Во-вторых, он предоставляет постоянные коллекции из Clojure (с добавленными универсальными шаблонами) и гарантирует, что элементы, добавленные в коллекции, неизменяемы. Производительность у них явно неплохая. Все коллекции неизменяемы, но для проверки реализуют интерфейсы коллекций Java (и дженерики). Мутация возвращает новые коллекции.
Отказ от ответственности: я разработчик этого
источник