Задан вопрос о том, как превратить массив в список. Большинство ответов до сих пор показывали, как создать новый список с тем же содержимым, что и массив, или со ссылкой на сторонние библиотеки. Однако для такого преобразования есть простые встроенные опции. Некоторые из них уже были обрисованы в других ответах (например, в этом ). Но я хотел бы указать и подробно описать определенные степени свободы для реализации здесь, а также показать потенциальные преимущества, недостатки и предостережения.
Следует сделать как минимум два важных различия:
- Должен ли результирующий список быть представлением для массива или он должен быть новым списком
- Должен ли полученный список быть изменяемым или нет
Здесь будут кратко описаны варианты, а полный пример программы показан внизу этого ответа.
Создание нового списка по сравнению с созданием представления в массиве
Когда результатом должен быть новый список, можно использовать один из подходов из других ответов:
List<Long> list = Arrays.stream(array).boxed().collect(Collectors.toList());
Но следует учитывать недостатки этого: массив из 1000000 long
значений будет занимать примерно 8 мегабайт памяти. Новый список также займет примерно 8 мегабайт. И, конечно же, при создании этого списка необходимо пройти по всему массиву. Во многих случаях создание нового списка просто не требуется. Вместо этого достаточно создать представление массива:
long array[] = { }
List<Long> list = asList(array);
(См. Пример внизу для реализации toList
метода)
Следствием наличия представления на массиве является то, что изменения в массиве будут видны в списке:
long array[] = { 12, 34, 56, 78 };
List<Long> list = asList(array);
System.out.println(list.get(1));
array[1] = 12345;
System.out.println(list.get(1));
К счастью, создание копии (то есть нового списка, на который не влияют изменения в массиве) из представления тривиально:
List<Long> copy = new ArrayList<Long>(asList(array));
Это настоящая копия, эквивалентная тому, что было достигнуто с помощью потокового решения, которое было показано выше.
Создание изменяемого представления или неизменяемого представления
Во многих случаях достаточно, чтобы список был доступен только для чтения . Содержимое результирующего списка часто не будет изменено, а будет передано только последующей обработке, которая только читает список.
Разрешение на внесение изменений в список вызывает ряд вопросов:
long array[] = { 12, 34, 56, 78 };
List<Long> list = asList(array);
list.set(2, 34567);
System.out.println(array[2]);
list.set(3, null);
list.add(99999);
Можно создать вид списка для изменяемого массива . Это означает, что изменения в списке, например установка нового значения по определенному индексу, будут видны в массиве.
Но невозможно создать структурно изменяемое представление списка . Это означает, что невозможно выполнять операции, влияющие на размер списка. Это просто потому, что размер базового массива нельзя изменить.
Ниже приводится MCVE, демонстрирующий различные варианты реализации и возможные способы использования полученных списков:
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.RandomAccess;
public class PrimitiveArraysAsLists
{
public static void main(String[] args)
{
long array[] = { 12, 34, 56, 78 };
List<Long> list = asList(array);
List<Long> unmodifiableList = asUnmodifiableList(array);
List<Long> copy = new ArrayList<Long>(asList(array));
System.out.println("array : " + Arrays.toString(array));
System.out.println("list : " + list);
System.out.println("unmodifiableList: " + unmodifiableList);
System.out.println("copy : " + copy);
System.out.println("Changing value at index 1 of the array...");
array[1] = 34567;
System.out.println("array : " + Arrays.toString(array));
System.out.println("list : " + list);
System.out.println("unmodifiableList: " + unmodifiableList);
System.out.println("copy : " + copy);
System.out.println("Changing value at index 2 of the list...");
list.set(2, 56789L);
System.out.println("array : " + Arrays.toString(array));
System.out.println("list : " + list);
System.out.println("unmodifiableList: " + unmodifiableList);
System.out.println("copy : " + copy);
try
{
unmodifiableList.set(2, 23456L);
}
catch (UnsupportedOperationException e)
{
System.out.println("Expected: " + e);
}
try
{
list.add(90L);
}
catch (UnsupportedOperationException e)
{
System.out.println("Expected: " + e);
}
try
{
list.set(2, null);
}
catch (NullPointerException e)
{
System.out.println("Expected: " + e);
}
}
private static List<Long> asUnmodifiableList(long array[])
{
Objects.requireNonNull(array);
class ResultList extends AbstractList<Long> implements RandomAccess
{
@Override
public Long get(int index)
{
return array[index];
}
@Override
public int size()
{
return array.length;
}
};
return new ResultList();
}
private static List<Long> asList(long array[])
{
Objects.requireNonNull(array);
class ResultList extends AbstractList<Long> implements RandomAccess
{
@Override
public Long get(int index)
{
return array[index];
}
@Override
public Long set(int index, Long element)
{
long old = array[index];
array[index] = element;
return old;
}
@Override
public int size()
{
return array.length;
}
};
return new ResultList();
}
}
Результат примера показан здесь:
array : [12, 34, 56, 78]
list : [12, 34, 56, 78]
unmodifiableList: [12, 34, 56, 78]
copy : [12, 34, 56, 78]
Changing value at index 1 of the array...
array : [12, 34567, 56, 78]
list : [12, 34567, 56, 78]
unmodifiableList: [12, 34567, 56, 78]
copy : [12, 34, 56, 78]
Changing value at index 2 of the list...
array : [12, 34567, 56789, 78]
list : [12, 34567, 56789, 78]
unmodifiableList: [12, 34567, 56789, 78]
copy : [12, 34, 56, 78]
Expected: java.lang.UnsupportedOperationException
Expected: java.lang.UnsupportedOperationException
Expected: java.lang.NullPointerException