Collectors.toUnmodifiableList против Collections.unmodifiableList в Java 10 - PullRequest
0 голосов
/ 03 октября 2018

Согласно doc метод Collections.unmodifiableList возвращает неизменяемое представление указанного списка.Является ли возвращаемый список действительно неизменяемым?Что мы подразумеваем под немодифицируемым представлением?

Согласно doc метод Collectors.toUnmodifiableList возвращает Collector, который накапливает входные элементы в немодифицируемый список в порядке встречи.Является ли возвращаемый список действительно неизменяемым?

Примечание. Под изменяемым я имею в виду представление, которое можно изменить с помощью операции set.Я хочу понять разницу и как они связаны?

Ответы [ 3 ]

0 голосов
/ 03 октября 2018

Метод Collections.unmodifiableList возвращает неизменяемое представление указанного списка.Неизменяемая коллекция представлений - это коллекция, которая не может быть изменена, а также является представлением резервной коллекции.Обратите внимание, что изменения в резервной коллекции все еще возможны, и если они происходят, они видны через неизменяемое представление.

List<String> srcList = Arrays.asList("Apple", "Banana", "Cherry");
var fruits = new ArrayList<>(srcList);
var unmodifiableList = Collections.unmodifiableList(fruits);     
fruits.set(0, "Apricot");
var modFruit = unmodifiableList.get(0);
System.out.println(modFruit); // prints Apricot

У нас может быть истинный неизменный список в Java 10 и позже.Есть два способа получить действительно неизменяемый список , как показано ниже:

  1. var unmodifiableList = List.copyOf(srcList); => печатает Apple
  2. var unmodifiableList = srcList.stream().collect(Collectors.toUnmodifiableList()); => печатает Apple

Таким образом, метод Collectors.toUnmodifiableList возвращает истинный неизменяемый список List.of, представленный в Java 9. Этот метод возвращает Collector, где в качестве метода Collections.unmodifiableList возвращается список.Согласно doc немодифицируемые списки имеют следующие характеристики:

  1. Они не модифицируемы.Элементы не могут быть добавлены, удалены или заменены.Вызов любого метода-мутатора в списке всегда приводит к выбрасыванию UnsupportedOperationException.Однако, если содержащиеся элементы сами являются изменяемыми, это может привести к изменению содержимого списка.
  2. Они запрещают нулевые элементы.Попытки создать их с нулевыми элементами приводят к NullPointerException.
  3. Они сериализуемы, если все элементы сериализуемы.
  4. Порядок элементов в списке такой же, как порядок предоставленныхаргументы или элементы в предоставленном массиве.
  5. Они value-based.Вызывающие абоненты не должны делать никаких предположений относительно личности возвращенных экземпляров.Фабрики могут создавать новые экземпляры или повторно использовать существующие.Поэтому чувствительные к идентификации операции с этими экземплярами (равенство ссылок (==), хэш-код идентификации и синхронизация) ненадежны и их следует избегать.
  6. Они сериализуются, как указано на странице Сериализованная форма.
0 голосов
/ 03 октября 2018

В качестве примечания, Collectors.toUnmodifiableList просто использует реализацию List::of, которая была добавлена ​​в java-9, финализатор для этой реализации:

list -> (List<T>)List.of(list.toArray()

, где list это простоArrayList;поэтому ваш вопрос сводится к тому, в чем разница между List::of и Collections::unmodifiableList (конечно, с оговоркой, что это не указано и происходит при текущей реализации ), и хотя я мог бы детализировать некоторые изразличия, уже есть хорошие (и многие другие, если вы будете искать).

Следует обратить внимание на то, как эти различные типы обрабатывают null s (другой момент, когда одинна самом деле представление , уже было предоставлено в других ответах):

List<Integer> left = Stream.of(1, 2, 3)
            .collect(Collectors.collectingAndThen(
                    Collectors.toList(),
                    Collections::unmodifiableList));

    System.out.println(left.contains(null));

    List<Integer> right = Stream.of(1, 2, 3)
            .collect(Collectors.toUnmodifiableList());

    System.out.println(right.contains(null)); 

В последней строке кода будет выдано исключение, вы можете даже не ожидать этого.

0 голосов
/ 03 октября 2018

Collections.unmodifiableList возвращает unmodifiable view, что означает, что вызов любого метода возвращенного List, который изменяет List, выдаст UnsupportedOperationException.Однако исходная List, переданная этому методу, все еще может быть изменена (при условии, что она может быть изменена), и такие модификации будут отражены в List, возвращаемом Collections.unmodifiableList.Следовательно, его можно считать «действительно неизменяемым», только если у вас нет доступа к оригинальному List.

Collectors.toUnmodifiableList, с другой стороны, используется для генерации нового List, которыйне поддается изменению, поэтому нет способа изменить это List.Поэтому это «поистине неизменяемое».

...