Коллекции.unmodifiableList и защитная копия
если я пишу
List<Integer> a1 = Arrays.asList(1, 2, 3);
List<Integer> a2 = Collections.unmodifiableList(a1);
a2
доступно только для чтения, но если я пишу
a1.set(0,10);
затем a2
также изменяется.
если в API сказано:
возвращает неизменяемое представление указанной коллекции. Этот метод позволяет модулям предоставлять пользователям доступ" только для чтения " к внутренним коллекции.
тогда почему, если я изменю исходную коллекцию, также будет скопирована целевая коллекция изменен?
возможно, я неправильно понял значение, и если да, то каков способ написать защитную копию этой коллекции?
7 ответов
Да, вы правильно поняли. Идея заключается в том, что объект, возвращенный umodifiableCollection
не может быть изменен напрямую, но может измениться другими способами (эффективно путем изменения внутренней коллекции напрямую).
пока что-то имеет доступ к внутреннему списку, "немодифицируемая" коллекция может быть изменена.
вот почему вы обычно создать коллекцию неизменяемым и убедитесь, что ничто не может добраться до внутренних список:
Collection<Integer> myUmodifiableCollection = Collection.umodifiableCollection(Arrays.asList(1, 2, 3));
так как ничто никогда не получает ссылку на List
создано asList
, это действительно неизменяемая коллекция.
преимущество этого подхода заключается в том, что вам не нужно копировать исходную коллекцию/список вообще, что позволяет избежать использования памяти и вычислительной мощности.
гуавы предоставляет ImmutableCollection
class (и его подклассы, такие как ImmutableList
), которые предоставляют истинные неизменяемые коллекции (обычно путем копирования источника).
может быть, я неправильно понял смысл, и если да, то как написать защитную копию этой коллекции?
как правило, вы бы использовали его таким образом:
private List<Integer> a1 = Arrays.asList(1, 2, 3);
public List<Integer> getUnmodifiable() {
return Collections.unmodifiableList(a1);
}
кто-то называет getUnmodifiable
и не имеет доступа к внутренней части вашего класса (т. е. они не могут получить доступ к закрытой переменной a1
), не сможет изменить возвращаемый список.
идея заключается в том, что вы не можете изменить список через a2
.
модификации a1
список действительно изменить то, что вы видите в a2
- это предназначено.
просто не имеют публичного способа доступа к списку a1
, и вы должны иметь то, что вы хотите :)
API говорит это внутренние коллекции в вашем случае это не внутренний
дело в том, что когда у вас есть частный список в классе A gettet для этого списка, то вы можете захотеть, чтобы вызывающие геттера не могли изменить список в случае ведьмы, вам придется вернуть umodifiable список. в противном случае возвращаемый список является просто ссылкой на ваш внутренний/частный список, и поэтому его содержимое может быть изменено.
инструкции:
Collections.unmodifiableList(a1);
возвращает оболочку над исходной коллекцией, чьи методы модификатора throw UnsupportedOperationException
.
обертка читается, что означает, что если вы измените a1
, изменения отражают на обернутой коллекции a2
.
a1
и a2
будет ссылаться на те же данные (память).
un-mofifiable часть приходит, только с a2
в качестве вступления.
изображения, если вы проходите a2
к методу, где вы ожидаете, что метод будет идемпотентным. такие случаи a2
помогает.
в резюме вы не можете изменять данные с помощью a2
указатель.
Если вам нужен неизменяемый и неизменяемый список или, другими словами, неизменяемая копия исходного списка без какой-либо зависимости от других библиотек, попробуйте следующее:
Collections.unmodifiableList(Collections.list(Collections.enumeration(sourceList)))
Collections.list()
копирует значения из перечисления.