Коллекции.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() копирует значения из перечисления.