См. JavaDocs и доклад Стюарта Маркса (или его предыдущие версии).
Для примеров кода я буду использовать следующее:
List<Integer> listOf = List.of(...);
List<Integer> asList = Arrays.asList(...);
List<Integer> unmodif = Collections.unmodifiableList(asList);
Структурная неизменность (или: неизменяемость)
Любая попытка структурных изменений List.of
приведет к созданию файла UnsupportedOperationException
. Сюда входят такие операции, как добавление , установка и удаление . Однако вы можете изменить содержимое объектов в списке (если объекты не являются неизменяемыми), чтобы список не был «полностью неизменяемым».
То же самое и с неизменяемыми списками, созданными с помощью Collections.unmodifiableList
. Только этот список является представлением исходного списка, поэтому он может измениться, если вы измените исходный список.
Arrays.asList
не является полностью неизменяемым, для него нет ограничений set
.
listOf.set(1, "a"); // UnsupportedOperationException
unmodif.set(1, "a"); // UnsupportedOperationException
asList.set(1, "a"); // modified unmodif! unmodif is not truly unmodifiable
Точно так же изменение массива поддержки (если вы его удерживаете) изменит список.
Структурная неизменяемость имеет множество побочных эффектов, связанных с защитным кодированием, параллелизмом и безопасностью, которые выходят за рамки этого ответа.
Нулевая враждебность
List.of
и любая коллекция, начиная с Java 1.5, не допускает использования null
в качестве элемента. Попытка пройтиnull
как элемент или даже поиск приведет к созданию файла NullPointerException
.
Поскольку Arrays.asList
это коллекция из 1.2 (платформа коллекций), она позволяет null
s.
listOf.contains(null); // NullPointerException
unmodif.contains(null); // allowed
asList.contains(null); // allowed
Сериализованная форма
Поскольку List.of
он был представлен в Java 9 и списки, созданные этим методом, имеют свою собственную (двоичную) сериализованную форму, они не могут быть десериализованы в более ранних версиях JDK (нет двоичной совместимости ). Однако вы можете де / сериализовать, например, с помощью JSON.
тождественность
Arrays.asList
внутренние вызовы new ArrayList
, что гарантирует ссылочное неравенство.
List.of
зависит от внутренней реализации. Возвращенные экземпляры могут иметь ссылочное равенство, но поскольку это не гарантируется, вы не можете на это полагаться.
asList1 == asList2; // false
listOf1 == listOf2; // true or false
Стоит отметить, что списки равны (через List.equals
), если они содержат одинаковые элементы в одном порядке, независимо от того, как они были созданы или какие операции они поддерживают.
asList.equals(listOf); // true i.f.f. same elements in same order
Реализация (предупреждение: детали могут изменяться в зависимости от версии)
Если количество элементов в списке List.of
равно 2 или меньше, элементы сохраняются в полях специализированного (внутреннего) класса. Примером может служить список, в котором хранятся 2 элемента (частичный источник):
static final class List2<E> extends AbstractImmutableList<E> {
private final E e0;
private final E e1;
List2(E e0, E e1) {
this.e0 = Objects.requireNonNull(e0);
this.e1 = Objects.requireNonNull(e1);
}
}
В противном случае они хранятся в массиве аналогично Arrays.asList
.
Эффективность времени и пространства
В List.of
реализации , которые являются полями на основе (размером <2) немного быстрее выполнить на некоторых операциях. Например, size()
может возвращать константу без извлечения длины массива и contains(E e)
не требует дополнительных затрат на итерацию.
Создание неизменяемого списка с помощью List.of
также выполняется быстрее. Сравните приведенный выше конструктор с двумя ссылочными назначениями (и даже с одним для произвольного количества элементов) для
Collections.unmodifiableList(Arrays.asList(...));
который создает 2 списка плюс другие накладные расходы. Что касается места, вы экономите UnmodifiableList
обертку плюс несколько копеек. В конечном итоге экономия в HashSet
эквиваленте более убедительна.
Время заключения: используйте, List.of
когда вам нужен список, который не меняется, и Arrays.asList
когда вам нужен список, который может изменяться (как показано выше).