Pytanie Utwórz ArrayList z tablicy


Mam tablicę, która jest zainicjalizowana jak:

Element[] array = {new Element(1), new Element(2), new Element(3)};

Chciałbym przekonwertować tę tablicę na obiekt klasy ArrayList.

ArrayList<Element> arraylist = ???;

2967
2017-10-01 14:38


pochodzenie


W języku Java9 -> Lista <ciąg> lista = Lista.of ("Witaj", "Świat", "od", "Java"); - MarekM
@MarekM Ta odpowiedź jest błędna, ponieważ nie zwraca ona odpowiedzi ArrayList. Plakat specjalnie o to prosił. - Tobias Weimer
Myślę, że nie używał interfejsu List, ponieważ jest to najlepsza praktyka. Ale jeśli chcesz tutaj, to - nowa ArrayList <> (List.of ("Hello", "World", "from", "Java")); - MarekM
Nie chodzi o używanie interfejsu, chodzi o to, że w twoim rozwiązaniu zwrócona lista jest niemodyfikowalna. To może być większy problem i powód, dla którego poprosił o ArrayList - Tobias Weimer


Odpowiedzi:


new ArrayList<>(Arrays.asList(array))

3971
2017-10-01 14:39



Tak. I w (najczęściej) przypadku, gdy chcesz tylko listę, new ArrayList połączenie też nie jest konieczne. - Calum
@Luron - po prostu użyj List<ClassName> list = Arrays.asList(array) - Pool
@Calum i @Bool - jak zaznaczono poniżej w odpowiedzi Alexa Millera, używając Arrays.asList(array) bez przekazywania go do nowego ArrayList obiekt naprawi rozmiar listy. Jednym z najczęstszych powodów używania ArrayList jest w stanie dynamicznie zmieniać jego rozmiar, a twoja sugestia zapobiegnie temu. - Code Jockey
Arrays.asList () to straszna funkcja, a ty nigdy nie powinieneś po prostu używać jej wartości zwracanej, tak jak jest. Łamie szablon listy, więc używaj go zawsze w przedstawionym tutaj formularzu, nawet jeśli wydaje się on zbędny. Dobra odpowiedź. - Adam
@Adam Proszę przestudiować javadoc dla java.util.List. Umowa dodania umożliwia im zgłoszenie wyjątku UnsupportedOperationException. docs.oracle.com/javase/7/docs/api/java/util/...  Wprawdzie z punktu widzenia obiektowego nie jest zbyt miłe, że wiele razy trzeba znać konkretną implementację, aby móc korzystać z kolekcji - był to pragmatyczny wybór projektu, aby zachować prosty układ. - lbalazscs


Dany:

Element[] array = new Element[] { new Element(1), new Element(2), new Element(3) };

Najprostszą odpowiedzią jest:

List<Element> list = Arrays.asList(array);

To zadziała dobrze. Ale niektóre zastrzeżenia:

  1. Lista zwrócona z asList ma ustalony rozmiar. Tak więc, jeśli chcesz móc dodawać lub usuwać elementy ze zwróconej listy w kodzie, musisz zawinąć je w nowy ArrayList. W przeciwnym razie dostaniesz UnsupportedOperationException.
  2. Lista zwrócona z asList() jest poparte oryginalną tablicą. Jeśli zmodyfikujesz oryginalną tablicę, lista również zostanie zmodyfikowana. To może być zaskakujące.

775
2017-10-01 15:39



Jaka jest złożoność obu operacji? Mam na myśli zi bez użycia jawnej konstrukcji listy tablic. - damned
Arrays.asList () tworzy jedynie ArrayList, owijając istniejącą tablicę tak, aby była O (1). - Alex Miller
Zawijanie w nowej tablicy ArrayList () powoduje, że wszystkie elementy listy o stałym rozmiarze są iterowane i dodawane do nowej tablicy ArrayList, tak więc jest to O (n). - Alex Miller
implementacja listy zwróconej przez asList () nie implementuje kilku metod List (takich jak add (), remove (), clear (), etc ...), co wyjaśnia wyjątek UnsupportedOperationException. zdecydowanie zastrzeżenie ... - sethro
Kiedy pytanie dotyczy "obiektu klasy ArrayList", myślę, że rozsądnie jest założyć, że klasa, do której się odnosi, jest java.util.ArrayList. Arrays.asList faktycznie zwraca a java.util.Arrays.ArrayList który nie jest instanceof druga klasa. Trzecim zastrzeżeniem jest to, że jeśli spróbujesz użyć go w kontekście wymagającym powyższego, to nie zadziała. - Dave L.


(stary wątek, ale tylko 2 centy, ponieważ nikt nie wspomniał o Guava lub innych bibliotekach i kilku innych szczegółach)

Jeśli możesz, użyj Guava

Warto wskazać sposób Guawy, który znacznie upraszcza te szantaże:

Stosowanie

Dla niezmiennej listy

Użyj ImmutableList klasa i jej of() i copyOf() metody fabryczne (elementy nie mogą być puste):

List<String> il = ImmutableList.of("string", "elements");  // from varargs
List<String> il = ImmutableList.copyOf(aStringArray);      // from array

For A Mutable List

Użyj Lists klasa i jej newArrayList() metody fabryczne:

List<String> l1 = Lists.newArrayList(anotherListOrCollection);    // from collection
List<String> l2 = Lists.newArrayList(aStringArray);               // from array
List<String> l3 = Lists.newArrayList("or", "string", "elements"); // from varargs

Należy również zwrócić uwagę na podobne metody dla innych struktur danych w innych klasach, na przykład w Sets.

Dlaczego Guava?

Główną atrakcją może być zmniejszenie bałaganu ze względu na generycznych dla bezpieczeństwa typu, jak korzystanie z Guawy metody fabryczne pozwalają typom wywnioskować większość czasu. Jednak argument ten zawiera mniej wody, ponieważ Java 7 przybyła z nowym operatorem diamentów.

Ale nie jest to jedyny powód (i Java 7 nie jest jeszcze dostępna): skrócona składnia jest również bardzo przydatna, a inicjatory metod, jak widać powyżej, pozwalają pisać bardziej ekspresyjny kod. Robisz w jednym wywołaniu Guava, co zajmuje 2 z bieżącymi kolekcjami Java.


Jeśli nie możesz ...

Dla niezmiennej listy

Użyj JDK Arrays klasa i jej asList() metoda fabryczna, opakowana w a Collections.unmodifiableList():

List<String> l1 = Collections.unmodifiableList(Arrays.asList(anArrayOfElements));
List<String> l2 = Collections.unmodifiableList(Arrays.asList("element1", "element2"));

Zwróć uwagę, że zwracany typ dla asList() jest List za pomocą betonu ArrayList wdrożenie, ale nie jest  java.util.ArrayList. Jest to typ wewnętrzny, który emuluje ArrayList ale w rzeczywistości bezpośrednio odwołuje się do przekazanej tablicy i sprawia, że ​​jest ona "zapisana" (modyfikacje są odzwierciedlane w tablicy).

Zabrania modyfikacji przez niektóre z nich List Metody API poprzez proste rozszerzenie AbstractList (więc dodawanie lub usuwanie elementów nie jest obsługiwane), ale pozwala na połączenia z set() aby zastąpić elementy. Tak więc ta lista nie jest prawdziwie niezmienna i nie można jej wywołać asList() powinien być owinięty Collections.unmodifiableList().

Zobacz następny krok, jeśli potrzebujesz listy zmiennych.

Dla listy Mutable

To samo, co powyżej, ale owinięte faktycznym java.util.ArrayList:

List<String> l1  = new ArrayList<String>(Arrays.asList(array));    // Java 1.5 to 1.6
List<String> l1b = new ArrayList<>(Arrays.asList(array));          // Java 1.7+
List<String> l2  = new ArrayList<String>(Arrays.asList("a", "b")); // Java 1.5 to 1.6
List<String> l2b = new ArrayList<>(Arrays.asList("a", "b"));       // Java 1.7+

W celach edukacyjnych: The Good ol 'Manual Way

// for Java 1.5+
static <T> List<T> arrayToList(final T[] array) {
  final List<T> l = new ArrayList<T>(array.length);

  for (final T s : array) {
    l.add(s);
  }
  return (l);
}

// for Java < 1.5 (no generics, no compile-time type-safety, boo!)
static List arrayToList(final Object[] array) {
  final List l = new ArrayList(array.length);

  for (int i = 0; i < array.length; i++) {
    l.add(array[i]);
  }
  return (l);
}

295
2017-11-16 17:16



+1 Ale pamiętaj, że List zwracane przez Arrays.asList jest zmienna, ponieważ możesz nadal set elementy - po prostu nie można zmienić rozmiaru. Do niezmiennych list bez Guava można wymienić Collections.unmodifiableList. - Paul Bellora
@haylem W twojej sekcji W celach edukacyjnych: The Good ol 'Manual Way, Twój arrayToList dla Java 1.5+ jest niepoprawna. Jesteś instancją listy Stringi próba pobrania łańcuchów z podanej tablicy, zamiast używania ogólnego typu parametru, T. Poza tym, dobrą odpowiedzią, i +1 za to, że jest jedyną, w tym ręczną. - afsantos


Ponieważ to pytanie jest dość stare, zaskakuje mnie, że nikt jeszcze nie zaproponował najprostszej formy:

List<Element> arraylist = Arrays.asList(new Element(1), new Element(2), new Element(3));

Od wersji Java 5, Arrays.asList() pobiera parametr varargs i nie musisz jawnie budować tablicy.


203
2018-06-22 11:30



W szczególności, List<String> a = Arrays.asList("first","second","third") - 18446744073709551615


new ArrayList<T>(Arrays.asList(myArray));

Upewnij się, że myArray jest tego samego typu co T. Otrzymasz błąd kompilatora, jeśli spróbujesz utworzyć List<Integer>z tablicy int, na przykład.


172
2017-10-01 14:40





Innym sposobem (choć zasadniczo równoważne z new ArrayList(Arrays.asList(array)) rozwiązanie pod względem wydajności:

Collections.addAll(arraylist, array);

77
2018-04-03 23:20





Prawdopodobnie potrzebujesz tylko Listy, a nie Tablicy. W takim przypadku możesz po prostu zrobić:

List<Element> arraylist = Arrays.asList(array);

62
2017-10-01 14:45



Będzie to wspierane przez oryginalną tablicę wejściową, dlatego (prawdopodobnie) chcesz ją zawinąć w nową ArrayList. - Bill the Lizard
Uważaj na to rozwiązanie. Jeśli spojrzysz, tablice NIE zwracają prawdziwej wartości java.util.ArrayList. Zwraca wewnętrzną klasę, która implementuje wymagane metody, ale nie można zmienić członków na liście. To tylko opakowanie wokół tablicy. - Mikezx6r
Możesz rzucić element List <Element> do ArrayList <Element> - monksy
@ Mikezx6r: mało korekta: jest to lista o stałym rozmiarze. Możesz zmienić elementy listy (set metoda), nie można zmienić rozmiaru listy (nie addlub remove elementy)! - Carlos Heuberger
Tak, z zastrzeżeniem, że zależy to od tego, co chcesz zrobić z listą. Warto wiedzieć, że jeśli OP po prostu chce przejrzeć elementy, to tablica wcale nie musi być konwertowana. - PaulMurrayCbr


Java 9

W Java 9, możesz użyć List.of statyczna metoda fabryczna w celu utworzenia List dosłowny. Coś jak poniżej:

List<Element> elements = List.of(new Element(1), new Element(2), new Element(3));

To by zwróciło niezmienny lista zawierająca trzy elementy. Jeśli chcesz zmienny lista, przekaż tę listę do ArrayList konstruktor:

new ArrayList<>(List.of(// elements vararg))

JEP 269: Wygodne metody fabryczne dla kolekcji

JEP 269 zapewnia pewne metody fabryki wygody dla Kolekcje Java API. Te niezmienne statyczne metody fabryczne są wbudowane w List, Set, i Map interfejsy w języku Java 9 i nowszych.


59
2018-04-17 16:58





Kolejna aktualizacja, prawie kończąca 2014 rok, możesz to zrobić również z Java 8:

ArrayList<Element> arrayList = Stream.of(myArray).collect(Collectors.toCollection(ArrayList::new));

Kilka znaków zostanie uratowanych, jeśli to może być po prostu List 

List<Element> list = Stream.of(myArray).collect(Collectors.toList());

54
2017-11-25 20:48



Najlepiej nie być zależnym od implementacji, ale Collectors.toList() faktycznie zwraca wartość ArrayList. - bcsb1001
nieprawidłowe użycie Stream.of (...); które utworzą strumień jednego elementu. Zamiast tego użyj Arrays.stream - Patrick Parker
Nie sądzę, że 2 opcje są poprawne, ale Arrays.stream jest nieco "lepszy", ponieważ można go utworzyć z ustalonym rozmiarem, stosując metodę przeciążania z argumentami "start", "koniec". Zobacz też: stackoverflow.com/a/27888447/2619091 - whyem


Aby przekonwertować tablicę na ArrayList, programiści często to robią:

List<String> list = Arrays.asList(arr);// this is wrong way..

Arrays.asList() zwróci ArrayList, która jest private static class inside Arrays, to nie jest klasa java.util.ArrayList. The java.util.Arrays.ArrayList klasa ma set(), get(), contains() metody, ale nie ma żadnych metod dodawania elementów, więc jego rozmiar jest ustalony. Aby utworzyć prawdziwą ArrayList, musisz:

ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr));

Konstruktor ArrayList może zaakceptować Typ kolekcji, który jest również super typem dla java.util.Arrays.ArrayList


47
2018-06-25 07:20



Nie jest to zła droga, jeśli potrzebujesz tylko Listi nie potrzebuję ArrayList, którego tak naprawdę nie robisz przez większość czasu. Przez większość czasu, gdy programiści tworzą ArrayList to z przyzwyczajenia, bardziej niż z potrzeby. - Christoffer Hammarström
Zgadzam się z @ ChristofferHammarström, oba są ważne List<String> list = Arrays.asList(arr); służy do tworzenia List i ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(arr)); służy do tworzenia ArrayList. Prawdopodobnie @Nepster właśnie skopiował wklejoną wyciąg z programcreek.com/2013/04/... - Nikhil Katre


Jeśli użyjesz :

new ArrayList<T>(Arrays.asList(myArray));

ty może Stwórz i wypełnij dwie listy! Wypełnienie dwukrotnie większej listy jest dokładnie tym, czego nie chcesz robić, ponieważ stworzy kolejną Object[] macierz za każdym razem, gdy pojemność musi zostać przedłużona.

Na szczęście implementacja JDK jest szybka i Arrays.asList(a[]) jest bardzo dobrze zrobione. Tworzy to rodzaj tablicy ArrayList o nazwie Arrays.ArrayList, w której dane Object [] wskazują bezpośrednio na tablicę.

// in Arrays
@SafeVarargs
public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}
//still in Arrays, creating a private unseen class
private static class ArrayList<E>

    private final E[] a;    
    ArrayList(E[] array) {
        a = array; // you point to the previous array
    }
    ....
}

Niebezpieczna strona jeśli zmienisz początkową tablicę, zmienisz List! Czy na pewno tego chcesz? Może tak, może nie.

Jeśli nie, najbardziej zrozumiałym sposobem jest zrobienie tego:

ArrayList<Element> list = new ArrayList<Element>(myArray.length); // you know the initial capacity
for (Element element : myArray) {
    list.add(element);
}

Lub jak powiedział @glglgl, możesz utworzyć inną niezależną ArrayList z:

new ArrayList<T>(Arrays.asList(myArray));

Uwielbiam korzystać Collections, Arrayslub Guawa. Ale jeśli nie pasuje lub nie czujesz tego, po prostu napisz inną nieelegancką linię.


30
2018-01-18 13:01



Nie widzę zasadniczej różnicy między twoją pętlą na końcu odpowiedzi a new ArrayList<T>(Arrays.asList(myArray)); część, której zniechęcasz do używania. Oba robią to samo i mają tę samą złożoność. - glglgl
Kolekcje one tworzą wskaźnik na początku tablicy. Moja pętla tworzy wiele wskaźników: po jednym dla każdego elementu tablicy. Jeśli więc pierwotna tablica ulegnie zmianie, moje poinery są nadal kierowane w stronę poprzednich wartości. - Nicolas Zozol
new ArrayList<T>(Arrays.asList(myArray)); robi to samo, kopiuje plik asList do ArrayList... - glglgl