Создает ли поток Java некоторый временный список при создании неизменного списка? - PullRequest
0 голосов
/ 24 января 2019

Поскольку ни один элемент не может быть добавлен в неизменяемый список, я думаю, что поток java сначала собирает элементы в список, а затем создает новый неизменяемый список с элементами из первого списка. Таким образом, существует два экземпляра списка, и первый экземпляр становится доступным для сборки мусора.

Итак, мой вопрос

  1. создает ли поток два объекта списка, как упомянуто выше?
  2. если нет, то как поток создает неизменный список?

Ответы [ 2 ]

0 голосов
/ 24 января 2019

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

Детали того, как это сделать, зависят от реализации, но здесь есть несколько возможностей:

  • Элементы накапливаются в ArrayList, который затем копируется в неизменный список.
  • Элементы накапливаются в ArrayList, и возвращается обертка, предотвращающая изменение (например, Collections.unmodifiableList.) Поскольку никакие другие объекты не имеют ссылок на исходный ArrayList, результат является настолько неизменным, насколько это возможно.
  • Элементы накапливаются в некоторой структуре, которая технически не является списком, такой как необработанный массив, и этот массив копируется или переносится в неизменяемый объект списка.

Выбор того, какая из этих реализаций зависит от конкретного Collector, который вы вызываете, например Collectors.toList() или ImmutableList.toImmutableList(). Детали этой реализации оставлены на усмотрение авторов этой библиотеки, которые могут использовать любую из этих стратегий.

0 голосов
/ 24 января 2019

Рассматривая следующий пример:

List<String> people
         = getPeople().stream()
                      .collect(collectingAndThen(toList(), Collections::unmodifiableList));

В этом примере я использую метод Collections::unmodifiableList, поэтому давайте проверим исходный код:

/**
 * Returns an unmodifiable view of the specified list.  This method allows
 * modules to provide users with "read-only" access to internal
 * lists.  Query operations on the returned list "read through" to the
 * specified list, and attempts to modify the returned list, whether
 * direct or via its iterator, result in an
 * <tt>UnsupportedOperationException</tt>.<p>
 *
 * The returned list will be serializable if the specified list
 * is serializable. Similarly, the returned list will implement
 * {@link RandomAccess} if the specified list does.
 *
 * @param  list the list for which an unmodifiable view is to be returned.
 * @return an unmodifiable view of the specified list.
 */
public static <T> List<T> unmodifiableList(List<? extends T> list) {
    return (list instanceof RandomAccess ?
            new UnmodifiableRandomAccessList<>(list) :
            new UnmodifiableList<>(list));
}

Как уже упоминалось в комментариях @Pshemo, UnmodifiableList работает как обертка для вашего списка, вы также можете проверить в исходном коде, что этот класс содержит список внутри:

 static class UnmodifiableList<E> extends UnmodifiableCollection<E>
                               implements List<E> {
     private static final long serialVersionUID = -283967356065247728L;
     final List<? extends E> list; // Here is the wrapped list

     UnmodifiableList(List<? extends E> list) {
         super(list);
         this.list = list;
     }
    ...
}

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

Итак, отвечая на ваш вопрос:

  • Поток создает неизменяемый список, используя такие методы, как Collections::unmodifiableList method
  • Внутренние потоки не добавляют ничего в другой список, поскольку ImmutableList просто работает как оболочка для Collection

Вы также можете проверить в документах и ​​источниках, чтобы понять, насколько точно работают эти неизменяемые связанные методы и объекты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...