В чем разница между списком.из и массивов.Аслан?


Java 9 представила новые методы фабрики коллекции,List.of:

List<String> strings = List.of("first", "second");

Итак, в чем разница между предыдущими и новыми опциями? То есть, в чем разница между этим:

Arrays.asList(1, 2, 3); 

и так:

List.of(1, 2, 3);
3 68

3 ответа:

Arrays.asList возвращает изменяемый список, в то время как список, возвращенный List.of непреложно:

List<Integer> list = Arrays.asList(1, 2, null);
list.set(1, 10); // OK

List<Integer> list = List.of(1, 2, 3);
list.set(1, 10); // Fails

Arrays.asList позволяет нулевые элементы в то время как List.of нет:

List<Integer> list = Arrays.asList(1, 2, null); // OK
List<Integer> list = List.of(1, 2, null); // Fails with a NullPointerException

contains метод ведет себя по-разному с нулями:

List<Integer> list = Arrays.asList(1, 2, 3);
list.contains(null); // Return false

List<Integer> list = List.of(1, 2, 3);
list.contains(null); // Throws NullPointerException

Arrays.asList возвращает представление переданного массива, поэтому изменения в массиве также будут отражены в списке. Ибо List.of это не так:

Integer[] array = {1,2,3};
List<Integer> list = Arrays.asList(array);
array[1] = 10;
System.out.println(list); // Prints [1, 10, 3]

Integer[] array = {1,2,3};
List<Integer> list = List.of(array);
array[1] = 10;
System.out.println(list); // Prints [1, 2, 3]    

различия между Arrays.asList и List.of

посмотреть JavaDocs и говорить Стюарт Маркс (или его предыдущие версии).

я буду использовать следующие примеры кода:

List<Integer> listOf = List.of(...);
List<Integer> asList = Arrays.asList(...);
List<Integer> unmodif = Collections.unmodifiableList(asList);

структурная неизменяемость (или: неизменяемость)

любая попытка структурно изменить List.of в результате UnsupportedOperationException. Это включает в себя такие операции, как добавить, set и удалить. Однако вы можете изменить содержимое объектов в списке (если объекты не являются неизменяемыми), поэтому список не является "полностью неизменяемым".

это та же участь для неизменяемых списков, созданных с помощью Collections.unmodifiableList. Только этот список является view исходный список, поэтому он может измениться, если вы измените исходный список.

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 (no двоичная совместимость). Однако вы можете де / сериализовать с помощью 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

реализация (предупреждение: детали могут меняться по версиям)

если количество элементов в списке!--8--> равно 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.

время и пространство эффективность

The List.of реализации, которые основаны на полях (размерsize() может возвращать константу без получения длины массива, и contains(E e) не требует итерационных накладных расходов.

построение неизменяемого списка через List.of тоже быстрее. Сравните приведенный выше конструктор с 2 ссылочными назначениями (и даже с одним для произвольного количества элементов) в

Collections.unmodifiableList(Arrays.asList(...));

что создает 2 списка плюс другие накладные расходы. С точки зрения пространства, вы сохраняете UnmodifiableList обертка плюс несколько пенни. В конечном счете, экономия в HashSet эквивалент более убедителен.


вывод: используйте List.of когда вы хотите, чтобы список, который не меняется, и Arrays.asList когда вы хотите список, который может измениться (как показано выше).

давайте суммируем различия между список.из и массивы.asList

  1. List.of лучше всего использовать, когда набор данных меньше и не изменяется, в то время как Arrays.asList может использоваться лучше всего в случае большого и динамического набора данных.

  2. List.of занимает очень меньше служебного пространства, потому что он имеет реализацию на основе полей и потребляет меньше места кучи, как с точки зрения фиксированных накладных расходов, так и на основе каждого элемента. в то время как Arrays.asList возьмите больше служебного пространства, потому что при инициализации он создает больше объектов в куче.

  3. коллекция возвращенным List.of является неизменяемым и, следовательно, потокобезопасным при сборе, возвращаемом Arrays.asList является изменяемым и не потокобезопасным. (Неизменяемые экземпляры коллекции обычно потребляют гораздо меньше памяти, чем их изменяемые аналоги.)

  4. List.of не дает null и Arrays.asList позволяет null элементы.