Создать изменяемый список из массива?

У меня есть массив, который я хотел бы превратить в List, чтобы изменить содержимое массива.

Stack Overflow имеет множество вопросов/ответов, касающихся Arrays.asList() и того, как он предоставляет только представление списка базового массива, и как попытка манипулировать результирующим списком обычно вызывает UnsupportedOperationException как методы, используемые для манипулирования списком (например, add(), remove(), и т. д.) не реализованы реализацией списка, предоставленной Arrays.asList().

Но я не могу найти пример того, как превратить массив в изменяемый список. Я полагаю, что могу перебирать массив и put() каждое значение в новый список, но мне интересно, существует ли интерфейс, который может сделать это для меня.


person ericsoco    schedule 25.07.2012    source источник


Ответы (5)


Один простой способ:

Foo[] array = ...;
List<Foo> list = new ArrayList<Foo>(Arrays.asList(array));

Это создаст изменяемый список, но это будет копия исходного массива. Изменение списка не изменит массив. Вы можете скопировать его позже, конечно, используя toArray.

Если вы хотите создать изменяемый представление для массива, я считаю, что вам придется реализовать это самостоятельно.

person Jon Skeet    schedule 25.07.2012
comment
Это вполне приемлемо для моих нужд. Я в порядке с отказом от исходного массива. - person ericsoco; 26.07.2012
comment
Arrays.asList возвращает представление массива с поддерживаемыми методами мутации, которые не влияют на размер списка. - person Timo Westkämper; 11.12.2012
comment
@TimoWestkämper: Да, но затем я создаю новый ArrayList из этого представления. - person Jon Skeet; 11.12.2012
comment
@jon-skeet Я знаю, я просто сказал, что Arrays.asList дает вам список, поддерживаемый массивом, с ограниченной изменчивостью, если вам нужно добавить/удалить/вставить, тогда упаковка ArrayList является лучшим подходом. - person Timo Westkämper; 11.12.2012
comment
Java необходимо сделать изменчивость/неизменность ясной во всех этих статических фабричных методах. Обидно узнать, что вы сделали неизменяемую вещь во время выполнения. - person dustinevan; 19.06.2018
comment
@dustinevan: документация довольно ясна. IMO: возвращает список фиксированного размера, поддерживаемый указанным массивом. (Изменения в возвращаемом списке записываются в массив.) - person Jon Skeet; 19.06.2018
comment
@JonSkeet не хочу тратить ваше время - спасибо за все, что вы делаете. Я просто хотел бы проголосовать за большую ясность в самих именах - я уверен, что документы ясны. Некоторые из нас танцуют между языками, и в других языках это достаточно очевидно. - person dustinevan; 19.06.2018

И если вы используете API коллекции Google (Guava):

Lists.newArrayList(myArray);
person vsingh    schedule 11.10.2013
comment
Это самый лаконичный ответ. Спасибо. - person eugene82; 24.06.2015
comment
Даже сама Гуава рекомендует использовать либо new ArrayList<>(Arrays.asList(...)) - javadoc для метода подразумевает, что он станет устаревшим, поскольку он недостаточно полезен. - person Logan Pickup; 03.01.2018
comment
2020 и до сих пор не устарел. Запрыгивай! - person markthegrea; 12.11.2020
comment
Это должен быть принятый ответ - person Kira Resari; 07.04.2021

Этот простой код с использованием Stream API, включенного в Java 8, создает изменяемый список (или представление), содержащий элементы вашего массива:

Foo[] array = ...;
List<Foo> list = Stream.of(array).collect(Collectors.toCollection(ArrayList::new));

Или, что равноправно:

List<Foo> list = Arrays.stream(array).collect(Collectors.toCollection(ArrayList::new));
person MikaelF    schedule 28.01.2017

Если вы используете Коллекции Eclipse (ранее Коллекции GS), вы можете использовать FastList.newListWith(...) или FastList.wrapCopy(...).

Оба метода принимают varargs, поэтому вы можете создать встроенный массив или передать существующий массив.

MutableList<Integer> list1 = FastList.newListWith(1, 2, 3, 4);

Integer[] array2 = {1, 2, 3, 4};
MutableList<Integer> list2 = FastList.newListWith(array2);

Разница между этими двумя методами заключается в том, копируется ли массив. newListWith() не копирует массив и поэтому занимает постоянное время. Вам следует избегать его использования, если вы знаете, что массив может быть изменен в другом месте.

Integer[] array2 = {1, 2, 3, 4};
MutableList<Integer> list2 = FastList.newListWith(array2);
array2[1] = 5;
Assert.assertEquals(FastList.newListWith(1, 5, 3, 4), list2);

Integer[] array3 = {1, 2, 3, 4};
MutableList<Integer> list3 = FastList.wrapCopy(array3);
array3[1] = 5;
Assert.assertEquals(FastList.newListWith(1, 2, 3, 4), list3);

Примечание. Я коммиттер Eclipse Collections.

person Craig P. Motlin    schedule 18.11.2013
comment
У вас есть хороший API коллекций. Первое, что я видел, могло бы отвлечь меня от моих собственных реализаций... единственное, что мне кажется недостающим, что я нахожу вообще полезным, это реализация отсортированного набора, поддерживаемая массивом (который я считаю намного более эффективным, чем древовидная реализация либо для данных, которые редко изменяются, либо для наборов, которые могут часто изменяться, но обычно содержат менее 10 или около того элементов). - person Jules; 13.03.2014

person    schedule
comment
@JonSkeet я знаю, что ваш комментарий от 2012 года, и сейчас я живу в будущем, но я предполагаю, что этот комментарий не удержался, учитывая, что моя IDE специально подчеркивает и говорит: «Эй, не объявляйте это с объявленным тип. он там не нужен? - person Brent Thoenen; 24.07.2019
comment
@BrentThoeenen: я не понимаю вашего комментария. Вы заметили, что мой комментарий относится к ревизии 1, в которой используется myNewArrayList = new ArrayList(...), т.е. необработанный тип? Есть разница между использованием оператора ромба, позволяющего компилятору обработать аргумент типа, и использованием необработанного типа. - person Jon Skeet; 24.07.2019
comment
Я разместил этот ответ и жил в забвении все это время, когда сам @JonSkeet прокомментировал мой ответ. Спасибо, Брент, за комментарий. - person Sid; 24.07.2019
comment
@JonSkeet ааа, мой плохой. я не проверял редакцию, которую вы комментировали. Я сделал неправильное предположение в том, что java 2012 года также предполагала пустой алмазный оператор как необработанный тип. Это мой б. Спасибо за ответ! - person Brent Thoenen; 25.07.2019