Створити змінний список із масиву?


84

У мене є масив, який я хотів би перетворити на List, щоб змінити вміст масиву.

Переповнення стека має багато питань / відповідей, адреса Arrays.asList()і як він забезпечує тільки уявлення списку базового масиву, і як намагається маніпулювати результуючий список, як правило , кидатися в UnsupportedOperationExceptionякості методів , використовуваних для управління списком (наприклад add(), remove()і т.д.) не реалізована реалізацією Списку, наданою Arrays.asList().

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

Відповіді:


122

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

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

Це створить змінний список - але це буде копія вихідного масиву. Зміна списку не призведе до зміни масиву. Ви можете скопіювати його пізніше, звичайно, використовуючи toArray.

Якщо ви хочете створити змінний вигляд масиву, я вважаю, що вам доведеться реалізувати це самостійно.


2
Arrays.asList повертає подання на масив із підтримкою тих мутуючих методів, які не впливають на розмір списку
Timo Westkämper

1
@ jon-skeet Я знаю, я просто стверджував, що Arrays.asList дає вам список із підтримкою масиву з обмеженою змінністю, якщо вам потрібно додати / видалити / вставити, тоді обгортання ArrayList - кращий підхід.
Timo Westkämper

4
Java повинна чітко визначити змінність / незмінність у всіх цих статичних заводських методах. Важко виявити, що ви зробили незмінну річ під час роботи.
Дастіневан

1
@dustinevan: Документація досить чітка. IMO: "Повертає список фіксованого розміру, підкріплений зазначеним масивом. (Зміни у списку, що повертається," записують "до масиву.)"
Джон Скіт,

1
@JonSkeet не хоче витрачати свій час - дякую за все, що робите. Я просто хотів би проголосувати за більшу чіткість самих імен - я впевнений, що документи чіткі. Деякі з нас танцюють між мовами, і це досить зрозуміло в інших мовах.
Дастіневан

21

А якщо ви використовуєте API колекції Google

Lists.newArrayList(myArray)

1
Це найкоротша відповідь. Дякую.
eugene82

2
Навіть сам Гуава рекомендує використовувати будь-який new ArrayList<>(Arrays.asList(...))- javadoc для методу означає, що він буде застарілим, оскільки він недостатньо корисний.
Пікап Логана

2020 і досі не застарілий. Стривай!
markthegrea

11

Цей простий код за допомогою API Stream, включеного в 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));

4

Якщо ви використовуєте колекції Eclipse (раніше GS Collections ), ви можете використовувати 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.


1
Це приємний API колекцій у вас там є. Перше, що я бачив, може спокусити мене від моїх власних реалізацій ... єдине, чого, здається, мені не вистачає, що я вважаю загалом корисним, - це реалізація відсортованого набору, підкріплена масивом (що, на мою думку, набагато ефективніше реалізація на основі дерева або для даних, які рідко модифікуються, або для наборів, які можуть бути часто модифіковані, але, як правило, містять менше 10 елементів).
Жуль

0
myNewArrayList = new ArrayList<>(Arrays.asList(myArray));

1
@JonSkeet, я знаю, що ваш коментар з 2012 року, і я живу в майбутньому зараз, але я припускаю, що цей коментар погано пройшов, враховуючи, що моя IDE спеціально підкреслює, і каже: "Гей, не заявляйте про це за допомогою оголошений тип. він вам там не потрібен "?
Brent Thoenen

1
@BrentThoenen: Я не розумію твого коментаря. Ви помітили, що мій коментар посилався на версію 1, яка використовувала myNewArrayList = new ArrayList(...), тобто необроблений тип? Існує різниця між "використанням алмазного оператора, щоб дозволити компілятору опрацювати аргумент типу", і "використанням необробленого типу".
Джон Скіт,

1
Я опублікував цю відповідь і весь цей час жив у забутті, що @JonSkeet Сам прокоментував мою відповідь. Дякуємо Brent за коментар.
Сід,

@JonSkeet ах, моє погано. я не перевіряв виправлення, яке ви коментували. Я зробив неправильне припущення в тому, що в 2012 році java також вважав порожній алмазний оператор сировинним типом. Це мій б. дякую за відповідь!
Brent Thoenen

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.