В Java 9 появились новые фабричные методы для списков List.of
:
List<String> strings = List.of("first", "second");
В чем разница между предыдущим и новым вариантом? То есть в чем разница между этим:
Arrays.asList(1, 2, 3);
и это:
List.of(1, 2, 3);
Ответы:
Arrays.asList
возвращает изменяемый список, в то время как список, возвращаемый функцией,List.of
является неизменным :Arrays.asList
допускает нулевые элементы, аList.of
не:contains
по-другому ведет себя с нулями:Arrays.asList
возвращает представление переданного массива, поэтому изменения в массиве также будут отражены в списке. ИбоList.of
это неправда:источник
List.contains(Object o)
javadoc : «Вызывает [...] исключение NullPointerException - если указанный элемент является нулевым и этот список не допускает нулевые элементы (необязательно)». Или из длинного введения интерфейса, которое немногие читают: «Некоторые реализации коллекций имеют ограничения на элементы, которые они могут содержать»List.of
действительно возвращают некоторыйImmutableList
тип, его фактическое название просто деталь непубличной реализаций. Если он был публичным и кто-тоList
снова его закинул, в чем разница? В чем разницаArrays.asList
, которая возвращает непубличнуюList
реализацию, которая выдает исключение при попыткеadd
илиremove
, или список, возвращаемыйCollections.unmodifiableList
which, не допускает никаких изменений вообще? Все дело в контрактах, указанных вList
интерфейсе. Интерфейсы коллекций с необязательными методами всегда были нечистыми ООП, начиная с Java 1.2…Различия между
Arrays.asList
иList.of
См. JavaDocs и доклад Стюарта Маркса (или его предыдущие версии).
Для примеров кода я буду использовать следующее:
Структурная неизменность (или: неизменяемость)
Любая попытка структурных изменений
List.of
приведет к созданию файлаUnsupportedOperationException
. Сюда входят такие операции, как добавление , установка и удаление . Однако вы можете изменить содержимое объектов в списке (если объекты не являются неизменяемыми), чтобы список не был «полностью неизменяемым».То же самое и с неизменяемыми списками, созданными с помощью
Collections.unmodifiableList
. Только этот список является представлением исходного списка, поэтому он может измениться, если вы измените исходный список.Arrays.asList
не является полностью неизменяемым, для него нет ограниченийset
.Точно так же изменение массива поддержки (если вы его удерживаете) изменит список.
Структурная неизменяемость имеет множество побочных эффектов, связанных с защитным кодированием, параллелизмом и безопасностью, которые выходят за рамки этого ответа.
Нулевая враждебность
List.of
и любая коллекция, начиная с Java 1.5, не допускает использованияnull
в качестве элемента. Попытка пройтиnull
как элемент или даже поиск приведет к созданию файлаNullPointerException
.Поскольку
Arrays.asList
это коллекция из 1.2 (платформа коллекций), она позволяетnull
s.Сериализованная форма
Поскольку
List.of
он был представлен в Java 9 и списки, созданные этим методом, имеют свою собственную (двоичную) сериализованную форму, они не могут быть десериализованы в более ранних версиях JDK (нет двоичной совместимости ). Однако вы можете де / сериализовать, например, с помощью JSON.тождественность
Arrays.asList
внутренние вызовыnew ArrayList
, что гарантирует ссылочное неравенство.List.of
зависит от внутренней реализации. Возвращенные экземпляры могут иметь ссылочное равенство, но поскольку это не гарантируется, вы не можете на это полагаться.Стоит отметить, что списки равны (через
List.equals
), если они содержат одинаковые элементы в одном порядке, независимо от того, как они были созданы или какие операции они поддерживают.Реализация (предупреждение: детали могут изменяться в зависимости от версии)
Если количество элементов в списке
List.of
равно 2 или меньше, элементы сохраняются в полях специализированного (внутреннего) класса. Примером может служить список, в котором хранятся 2 элемента (частичный источник):В противном случае они хранятся в массиве аналогично
Arrays.asList
.Эффективность времени и пространства
В
List.of
реализации , которые являются полями на основе (размером <2) немного быстрее выполнить на некоторых операциях. Например,size()
может возвращать константу без извлечения длины массива иcontains(E e)
не требует дополнительных затрат на итерацию.Создание неизменяемого списка с помощью
List.of
также выполняется быстрее. Сравните приведенный выше конструктор с двумя ссылочными назначениями (и даже с одним для произвольного количества элементов) длякоторый создает 2 списка плюс другие накладные расходы. Что касается места, вы экономите
UnmodifiableList
обертку плюс несколько копеек. В конечном итоге экономия вHashSet
эквиваленте более убедительна.Время заключения: используйте,
List.of
когда вам нужен список, который не меняется, иArrays.asList
когда вам нужен список, который может изменяться (как показано выше).источник
Arrays.asList
не полностью изменяемый.asList.add(1);
бросаетUnsupportedOperationException
.List.of
время, когда люди могут захотеть позвонитьcontains
и не удивиться исключению NullPointerException.Пусть суммировать различия между List.of и Arrays.asList
List.of
лучше всего использовать, когда набор данных меньше и не изменяется, аArrays.asList
лучше всего использовать в случае большого и динамического набора данных.List.of
занимают очень меньше служебного пространства, потому что он реализован на основе полей и потребляет меньше места в куче, как с точки зрения фиксированных служебных данных, так и для отдельных элементов. в то время какArrays.asList
занимают больше служебного пространства, потому что при инициализации он создает больше объектов в куче.Коллекция, возвращаемая
List.of
объектом, является неизменной и, следовательно, потокобезопасной, в то время как Коллекция, возвращаемаяArrays.asList
объектом, является изменяемой и не потокобезопасной. (Неизменяемые экземпляры коллекций обычно потребляют гораздо меньше памяти, чем их изменяемые аналоги.)List.of
не допускает нулевые элементы, аArrays.asList
допускает нулевые элементы.источник
Arrays.asList
versusList.of
, учитывая, что первое - это буквально просто оболочка вокруг массива. По крайней мере , реализация OpenJDK имеет чрезвычайно небольшие накладные расходы. Фактически,List.of
необходимо будет сделать копии любого переданного массива, поэтому, если сам массив не собирается в ближайшее время быть GC, похоже,List.of
имеет значительно больший объем памяти.List.of(x)
иList.of(x, y)
более эффективны, потому что они вообще не выделяют массивыList.of
методы не обязаны каждый раз возвращать новые списки. Эти списки имеют неопределенную идентичность, поэтому на уровне JVM может выполняться кэширование, дедупликация или скаляризация. Если не в этой версии, то, возможно, в следующей. Это разрешено договором. Напротив, этоArray.asList
зависит от идентификатора массива, который вы передаете, так как результирующий список является изменяемым представлением массива, отражающим все изменения в двух направлениях.Помимо приведенных выше ответов, существуют определенные операции, по которым оба
List::of
иArrays::asList
различаются:Подробнее о Коллекциях :: singletonList Vs. Список
источник