Konwertowanie tablicy na listę w Javie

1027

Jak przekonwertować tablicę na listę w Javie?

Użyłem, Arrays.asList()ale zachowanie (i podpis) jakoś zmieniło się z Java SE 1.4.2 (dokumenty są teraz w archiwum) na 8, a większość fragmentów znalezionych w Internecie używa zachowania 1.4.2.

Na przykład:

int[] spam = new int[] { 1, 2, 3 };
Arrays.asList(spam)
  • na 1.4.2 zwraca listę zawierającą elementy 1, 2, 3
  • w wersji 1.5.0+ zwraca listę zawierającą spam spamowy

W wielu przypadkach powinno być łatwe do wykrycia, ale czasami może się niepostrzeżenie wymknąć:

Assert.assertTrue(Arrays.asList(spam).indexOf(4) == -1);
Alexandru
źródło
20
Myślę, że twój przykład jest zepsuty Arrays.asList(new int[] { 1, 2, 3 }):; zdecydowanie nie skompilować w Java 1.4.2, ponieważ int[]jest nieObject[] .
Joachim Sauer
1
Och, możesz mieć rację. Nie miałem kompilatora Java 1.4.2, aby przetestować mój przykład przed opublikowaniem. Teraz, po twoim komentarzu i odpowiedzi Joe, wszystko ma o wiele więcej sensu.
Alexandru,
1
Myślałem, że Autoboxing obejmowałby konwersję z prymitywnej na otokową klasę całkowitą. Możesz najpierw wykonać rzutowanie, a następnie powyższy kod Arrays.asListpowinien działać.
Koński głos
2
Stream.boxed () Java 8 zajmie się autoboxingiem i może być do tego użyty. Zobacz moją odpowiedź poniżej .
Ibrahim Arief
Rozwiązanie Java 8: stackoverflow.com/questions/2607289/…
akhil_mittal

Odpowiedzi:

1430

W twoim przykładzie dzieje się tak, ponieważ nie możesz mieć listy typu pierwotnego. Innymi słowy,List<int> nie jest to możliwe.

Możesz jednak List<Integer>użyć Integerklasy, która otacza intprymityw. Konwersja tablicy do Listze Arrays.asListsposobem gospodarczym.

Integer[] spam = new Integer[] { 1, 2, 3 };
List<Integer> list = Arrays.asList(spam);

Zobacz ten kod uruchamiany na żywo w IdeOne.com .

Joe Daley
źródło
112
Lub nawet prościej: Arrays.asList (1, 2, 3);
Kong
45
Skąd wie, żeby nie tworzyć List<Integer[]>?
Thomas Ahle,
25
Nie działa w Javie 5+.
djechlin
6
@ThomasAhle Nie tworzy List <Integer []> tworzy obiekt List <Integer>. A jeśli chcesz być bezpieczny, pisz: Tablice. <Integer> asList (spam);
user1712376
6
@ThomasAhle To dobre pytanie. Domyślam się, że to tylko reguła w kompilatorze Java. Na przykład poniższy kod zwraca List <Integer []> Integer[] integerArray1 = { 1 }; Integer[] integerArray2 = { 2 }; List<Integer[]> integerArrays = Arrays.asList(integerArray1, integerArray2);
Simon
167

W Javie 8 możesz używać strumieni:

int[] spam = new int[] { 1, 2, 3 };
Arrays.stream(spam)
      .boxed()
      .collect(Collectors.toList());
Ibrahim Arief
źródło
To miłe, ale nie zadziała boolean[]. Myślę, że to dlatego, że tak samo łatwo jest zrobić Boolean[]. To prawdopodobnie lepsze rozwiązanie. W każdym razie to ciekawe dziwactwo.
GlenPeterson
138

Mówiąc o sposobie konwersji, zależy to od tego, dlaczego potrzebujesz swojego List. Jeśli potrzebujesz tylko do odczytu danych. Ok, no to dajesz:

Integer[] values = { 1, 3, 7 };
List<Integer> list = Arrays.asList(values);

Ale jeśli zrobisz coś takiego:

list.add(1);

dostajesz java.lang.UnsupportedOperationException. Więc w niektórych przypadkach potrzebujesz tego:

Integer[] values = { 1, 3, 7 };
List<Integer> list = new ArrayList<Integer>(Arrays.asList(values));

Pierwsze podejście faktycznie nie konwertuje tablicy, ale „reprezentuje” ją jak List. Ale tablica jest pod maską i ma wszystkie swoje właściwości, takie jak stała liczba elementów. Pamiętaj, że musisz podać typ podczas konstruowania ArrayList.

Roman Nikitchenko
źródło
1
„niezmienność” zmieszało mnie na chwilę. Możesz oczywiście zmienić wartości tablicy. Nie można jednak zmienić jego rozmiaru.
Tim Pohlmann
125

Problem polega na tym, że varargs został wprowadzony w Javie 5 i niestety Arrays.asList()został również przeciążony wersją vararg. Tak Arrays.asList(spam)jest rozumiany przez kompilator Java5 jako parametr vararg tablic int.

Problem ten wyjaśniono bardziej szczegółowo w Effective Java 2nd Ed., Rozdział 7, pozycja 42.

Péter Török
źródło
4
Rozumiem, co się stało, ale nie dlaczego nie jest to udokumentowane. Szukam alternatywnego rozwiązania bez ponownego montażu koła.
Alexandru
2
@UsmanIsmail Począwszy od Java 8, możemy używać strumieni do tej konwersji. Zobacz moją odpowiedź poniżej .
Ibrahim Arief
109

Wydaje się, że trochę późno, ale oto moje dwa centy. Nie możemy mieć List<int>za intto prymitywny typ tak możemy mieć tylko List<Integer>.

Java 8 (tablica int)

int[] ints = new int[] {1,2,3,4,5};
List<Integer> list11 =Arrays.stream(ints).boxed().collect(Collectors.toList()); 

Java 8 i niższe (tablica liczb całkowitych)

Integer[] integers = new Integer[] {1,2,3,4,5};
List<Integer> list21 =  Arrays.asList(integers); // returns a fixed-size list backed by the specified array.
List<Integer> list22 = new ArrayList<>(Arrays.asList(integers)); // good
List<Integer> list23 = Arrays.stream(integers).collect(Collectors.toList()); //Java 8 only

Potrzebujesz ArrayList, a nie List?

Jeśli chcemy konkretnej implementacji Listnp. ArrayListMożemy użyć toCollectionjako:

ArrayList<Integer> list24 = Arrays.stream(integers)
                          .collect(Collectors.toCollection(ArrayList::new));

Dlaczego list21nie można modyfikować strukturalnie?

Kiedy używamy, Arrays.asListrozmiar zwracanej listy jest ustalony, ponieważ zwracana lista nie jest java.util.ArrayList, ale prywatną klasą statyczną zdefiniowaną w środku java.util.Arrays. Więc jeśli dodamy lub usuniemy elementy ze zwróconej listy, UnsupportedOperationExceptionzostanie wygenerowany znak „ an” . Więc powinniśmy iść, list22kiedy chcemy zmodyfikować listę. Jeśli mamy Javę 8, możemy również skorzystać z list23.

Dla jasności list21można zmodyfikować w tym sensie, że możemy wywoływać, list21.set(index,element)ale ta lista może nie być modyfikowana strukturalnie, tj. Nie może dodawać ani usuwać elementów z listy. Możesz również sprawdzić to pytanie .


Jeśli chcemy niezmienną listę, możemy ją zawinąć jako:

List<Integer> list 22 = Collections.unmodifiableList(Arrays.asList(integers));

Inną kwestią do odnotowania jest to, że metoda Collections.unmodifiableList zwraca niemodyfikowalny widok podanej listy. Kolekcja niemodyfikowalna jest kolekcją niemodyfikowalną, a także widokiem na kolekcję podkładową. Należy pamiętać, że zmiany w kolekcji kopii zapasowych mogą być nadal możliwe, a jeśli wystąpią, są widoczne w widoku niemodyfikowalnym.

Możemy mieć naprawdę niezmienną listę w Javie 9 i 10.

Naprawdę niezmienna lista

Java 9:

String[] objects = {"Apple", "Ball", "Cat"};
List<String> objectList = List.of(objects);

Java 10 (lista prawdziwie niezmienna) na dwa sposoby:

  1. List.copyOf(Arrays.asList(integers))
  2. Arrays.stream(integers).collect(Collectors.toUnmodifiableList());

Sprawdź również moją odpowiedź, aby uzyskać więcej.

akhil_mittal
źródło
@BasilBourque Miałem na myśli, że nie mogę modyfikować struktury listy poprzez dodawanie / usuwanie, ale mogę zmieniać elementy.
akhil_mittal
Rzeczywiście, wypróbowałem trochę kodu i potwierdziłem, że wywoływanie List::addi List::removeniepowodzenie z listą zwróconą przez Arrays.asList. JavaDoc dla tej metody jest źle napisany i niejasny w tej kwestii. W trzecim czytaniu przypuszczam, że wyrażenie „o stałym rozmiarze” miało oznaczać, że nie można dodawać ani usuwać elementów.
Basil Bourque,
12

Jeszcze krótszy:

List<Integer> list = Arrays.asList(1, 2, 3, 4);
Witalij Sokołow
źródło
11

Niedawno musiałem przekonwertować tablicę na listę. Później program przefiltrował listę próbując usunąć dane. Korzystając z funkcji Arrays.asList (tablica), tworzysz kolekcję o stałym rozmiarze: nie możesz ani dodawać, ani usuwać. Ten wpis wyjaśnia problem lepiej niż potrafię: Dlaczego otrzymuję UnsupportedOperationException podczas próby usunięcia elementu z listy? .

W końcu musiałem wykonać konwersję „ręczną”:

    List<ListItem> items = new ArrayList<ListItem>();
    for (ListItem item: itemsArray) {
        items.add(item);
    }

Przypuszczam, że mogłem dodać konwersję z tablicy do listy za pomocą operacji List.addAll (items).

Steve Gelman
źródło
11
new ArrayList<ListItem>(Arrays.asList(itemsArray))zrobiłby to samo
Marco13
1
@BradyZhu: Przyznaję, że powyższa odpowiedź nie rozwiązuje mojego problemu z tablicą o stałym rozmiarze, ale w zasadzie mówisz tutaj o RTFM, która zawsze ma złą formę. Wyjaśnij, co jest nie tak z odpowiedzią lub nie zawracaj sobie głowy komentowaniem.
Steve Gelman,
2
Narzędzia inspekcyjne mogą wyświetlać ostrzeżenie tutaj i podałeś przyczynę. Nie ma potrzeby ręcznego kopiowania elementów, użyj Collections.addAll(items, itemsArray)zamiast tego.
Darek Kay
Po prostu traf ten wyjątek. Obawiam się, że odpowiedź Marco13 powinna być poprawną odpowiedzią. Być może będę musiał przejść przez cały rok, aby naprawić wszystkie wyjątki „asList”.
7

Korzystanie z tablic

Jest to najprostszy sposób na konwersję tablicy List. Jeśli jednak spróbujesz dodać nowy element lub usunąć istniejący element z listy, UnsupportedOperationExceptionzostanie wyrzucony.

Integer[] existingArray = {1, 2, 3};
List<Integer> list1 = Arrays.asList(existingArray);
List<Integer> list2 = Arrays.asList(1, 2, 3);

// WARNING:
list2.add(1);     // Unsupported operation!
list2.remove(1);  // Unsupported operation!

Korzystanie z ArrayList lub innych implementacji listy

forPętli można użyć do dodania wszystkich elementów tablicy do Listimplementacji, np . ArrayList:

List<Integer> list = new ArrayList<>();
for (int i : new int[]{1, 2, 3}) {
  list.add(i);
}

Korzystanie ze Stream API w Javie 8

Możesz przekształcić tablicę w strumień, a następnie zebrać strumień przy użyciu różnych kolektorów: Domyślny kolektor w Javie 8 jest używany ArrayListza ekranem, ale możesz także narzucić preferowaną implementację.

List<Integer> list1, list2, list3;
list1 = Stream.of(1, 2, 3).collect(Collectors.toList());
list2 = Stream.of(1, 2, 3).collect(Collectors.toCollection(ArrayList::new));
list3 = Stream.of(1, 2, 3).collect(Collectors.toCollection(LinkedList::new));

Zobacz też:

Mincong Huang
źródło
6

Kolejne obejście, jeśli używasz apache commons-lang:

int[] spam = new int[] { 1, 2, 3 };
Arrays.asList(ArrayUtils.toObject(spam));

Gdzie ArrayUtils.toObject konwertuje int[]naInteger[]

alaster
źródło
5

musisz rzucić się na tablicę

Arrays.asList((Object[]) array)
Giancarlo Frison
źródło
3
java: typy niezgodne: int [] nie można przekonwertować na java.lang.Object []
dVaffection
@dVaffection Następnie rzutuj na int []. Ważną częścią jest rzutowanie na tablicę.
Nebril
5

Jednowarstwowy:

List<Integer> list = Arrays.asList(new Integer[] {1, 2, 3, 4});
Bhuszan
źródło
5

W Javie 9 masz jeszcze bardziej eleganckie rozwiązanie polegające na użyciu niezmiennych list za pomocą nowej metody fabryki wygody List.of:

List<String> immutableList = List.of("one","two","three");

(bezwstydnie skopiowane stąd )

Pierluigi Vernetto
źródło
Do zapoznania się z niektórymi szczegółami technicznymi kryjącymi się za tą informacją, zob. JEP 269: Metody fabryk dogodnych dla kolekcji oraz wykład Stuarta Marksa , głównego autora.
Basil Bourque
5

Jeśli celujesz w Javę 8 (lub nowszą wersję), możesz spróbować:

int[] numbers = new int[] {1, 2, 3, 4};
List<Integer> integers = Arrays.stream(numbers)
                        .boxed().collect(Collectors.<Integer>toList());

UWAGA:

Zwróć uwagę na Collectors.<Integer>toList()tę ogólną metodę, która pozwala uniknąć błędu „Niezgodność typu: nie można przekonwertować z List<Object>na List<Integer>”.

nybon
źródło
4
  1. Używanie Guawy:

    Integer[] array = { 1, 2, 3};
    List<Integer> list = Lists.newArrayList(sourceArray);
  2. Korzystanie z kolekcji Apache Commons:

    Integer[] array = { 1, 2, 3};
    List<Integer> list = new ArrayList<>(6);
    CollectionUtils.addAll(list, array);
Danail Tsvetanov
źródło
3

Jeśli to pomaga: miałem ten sam problem i po prostu napisałem ogólną funkcję, która pobiera tablicę i zwraca ArrayList tego samego typu o tej samej treści:

public static <T> ArrayList<T> ArrayToArrayList(T[] array) {
    ArrayList<T> list = new ArrayList<T>();
    for(T elmt : array) list.add(elmt);
    return list;
}
kleines filmröllchen
źródło
Co jeśli to nie pomoże? Co wtedy zrobiłeś? ... jk :)
Sᴀᴍ Onᴇᴌᴀ
2

Biorąc pod uwagę tablicę:

    int[] givenArray = {2,2,3,3,4,5};

Konwertowanie tablicy liczb całkowitych na listę liczb całkowitych

Jeden sposób: boxed () -> zwraca IntStream

    List<Integer> givenIntArray1 = Arrays.stream(givenArray)
                                  .boxed()
                                  .collect(Collectors.toList());

Drugi sposób: zamapuj każdy element strumienia na liczbę całkowitą, a następnie zbierz

UWAGA: Korzystając z mapToObj, możesz ukryć każdy element int w strumieniu łańcucha, strumieniu znaków itp., Umieszczając i do (char) i

    List<Integer> givenIntArray2 = Arrays.stream(givenArray)
                                         .mapToObj(i->i)
                                         .collect(Collectors.toList());

Konwertowanie jednego typu tablicy na inny typ Przykład:

List<Character> givenIntArray2 = Arrays.stream(givenArray)
                                             .mapToObj(i->(char)i)
                                             .collect(Collectors.toList());
Arpan Saini
źródło
1

To zależy od tego, którą wersję Java próbujesz-

Java 7

 Arrays.asList(1, 2, 3);

LUB

       final String arr[] = new String[] { "G", "E", "E", "K" };
       final List<String> initialList = new ArrayList<String>() {{
           add("C");
           add("O");
           add("D");
           add("I");
           add("N");
       }};

       // Elements of the array are appended at the end
       Collections.addAll(initialList, arr);

LUB

Integer[] arr = new Integer[] { 1, 2, 3 };
Arrays.asList(arr);

W Javie 8

int[] num = new int[] {1, 2, 3};
List<Integer> list = Arrays.stream(num)
                        .boxed().collect(Collectors.<Integer>toList())

Odniesienia - http://www.codingeek.com/java/how-to-convert-array-to-list-in-java/

Hitesh Garg
źródło
1

Czy możesz poprawić tę odpowiedź, ponieważ tego używam, ale nie jestem w 100% jasny. Działa dobrze, ale IntelliJ dodał nową WeatherStation [0]. Dlaczego 0?

    public WeatherStation[] removeElementAtIndex(WeatherStation[] array, int index)
    {
        List<WeatherStation> list = new ArrayList<WeatherStation>(Arrays.asList(array));
        list.remove(index);
        return list.toArray(new WeatherStation[0]);
    }

DevilCode
źródło
Dlaczego powinno się poprawić swoje pytanie? Albo znasz odpowiedź, albo nie. Powinieneś oczywiście udzielić odpowiedzi, która naprawdę pomaga innym, a nie takiej, która dezorientuje bardziej niż pomaga.
HimBromBeere
-2

użyj dwóch linii kodu, aby przekonwertować tablicę na listę, jeśli użyjesz go w wartości całkowitej, musisz użyć typu autoboxing dla pierwotnego typu danych

  Integer [] arr={1,2};
  Arrays.asList(arr);
yousef
źródło