См. 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 (платформа коллекций), она позволяет nulls.
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когда вам нужен список, который может изменяться (как показано выше).