Chciałem stworzyć listę opcji do celów testowych. Na początku zrobiłem to:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
Następnie zmieniłem kod w następujący sposób:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Czy jest na to lepszy sposób?
java
collections
arraylist
initialization
Makaron
źródło
źródło
ArrasyList<String> places = ["Buenos Aires", "Córdoba", "La Plata"]
Odpowiedzi:
Właściwie prawdopodobnie „najlepszym” sposobem na zainicjowanie
ArrayList
metody jest napisana przez ciebie metoda, ponieważ nie trzeba jejList
w żaden sposób tworzyć :Problem polega na tym, że aby odwołać się do tego
list
wystąpienia , konieczne jest sporo pisania .Istnieją alternatywy, takie jak utworzenie anonimowej klasy wewnętrznej za pomocą inicjatora instancji (znanego również jako „inicjalizacja podwójnego nawiasu klamrowego”):
Jednak nie przepadam za tą metodą, ponieważ to, co kończysz, to podklasa,
ArrayList
która ma inicjalizator instancji, a ta klasa jest tworzona tylko w celu stworzenia jednego obiektu - to wydaje mi się trochę przesadne.Byłoby miło, gdyby propozycja Collection Literals dla Project Coin została zaakceptowana (miała zostać wprowadzona w Javie 7, ale raczej nie będzie częścią Java 8).
Niestety nie pomoże ci to tutaj, ponieważ zainicjuje niezmienne
List
zamiastArrayList
, a ponadto nie jest jeszcze dostępne, jeśli kiedykolwiek będzie.źródło
Byłoby łatwiej, gdyby po prostu zadeklarować go jako
List
- czy to musi być ArrayList?Lub jeśli masz tylko jeden element:
Oznaczałoby to, że
places
jest niezmienny (próba zmiany spowodujeUnsupportedOperationException
wygenerowanie wyjątku).Aby utworzyć konkretną listę,
ArrayList
którą można modyfikować , możesz utworzyć jąArrayList
z listy niezmiennej:źródło
ArrayList
, lepiej byłoby zmienić deklarację naList
. Podaj interfejsy, a nie implementacje.asList(...)
zwraca stały rozmiar,List
który wysadza się w wyniku mutacji operacji, takich jakremove
iclear
, rzeczy, któreList
kontrakt twierdzi, że obsługuje. Nawet jeśli pozostawiłeś deklarację jakoList
, nadal musisz użyćList l = new ArrayList(asList(...))
, aby uzyskać obiekt, który nie zgłasza wyjątków OperationNotSupported. Liskov Zastępstwo Zasada ktoś?remove
iclear
są operacjami opcjonalnymi wList
, więcasList(...)
jest zgodny z umową. Nigdzie PO nie mówi, że musi dodać więcej elementów później, przykład jest po prostu takiList
, który należy zainicjować trzema elementami.Prosta odpowiedź
W Javie 9 lub nowszej
List.of()
dodano później :W Javie 10 lub nowszej można to skrócić za pomocą
var
słowa kluczowego.To da ci niezmienne
List
, więc nie można tego zmienić.To jest to, czego chcesz w większości przypadków, gdy przygotowujesz to do wypełnienia.
Java 8 lub wcześniejsza:
To da ci
List
wsparcie przez tablicę, więc nie może zmienić długości.Ale możesz zadzwonić
List.set
, więc nadal można go modyfikować .Możesz
Arrays.asList
skrócić jeszcze bardziej za pomocą importu statycznego:Import statyczny:
Co każde nowoczesne IDE zasugeruje i automatycznie zrobi dla Ciebie.
Na przykład w IntelliJ IDEA naciskasz
Alt+Enter
i wybieraszStatic import method...
.Jednak nie polecam skracania
List.of
metodyof
, ponieważ staje się to mylące.List.of
jest już wystarczająco krótki i dobrze czyta.Korzystanie z
Stream
sDlaczego to musi być
List
?W Javie 8 lub nowszej możesz użyć
Stream
bardziej elastycznego:Możesz połączyć następujące elementy
Stream
:Lub możesz przejść z
Stream
doList
:Ale najlepiej po prostu użyj
Stream
bez zbierania go doList
.Jeśli ty naprawdę potrzebujesz
java.util.ArrayList
(Prawdopodobnie nie.)
Cytując JEP 269 (moje podkreślenie):
Jeśli chcesz zarówno wstępnie wypełnić an, jak
ArrayList
i dodać do niego później (dlaczego?), Użyjlub w Javie 8 lub wcześniejszej:
lub za pomocą
Stream
:Ale znowu, lepiej po prostu użyć
Stream
bezpośrednio zamiast zbierać go doList
.Program do interfejsów, a nie do implementacji
Powiedziałeś, że zadeklarowałeś listę jako
ArrayList
w swoim kodzie, ale powinieneś to zrobić tylko wtedy, gdy używasz jakiegoś członka,ArrayList
którego nie maList
.Czego najprawdopodobniej nie robisz.
Zazwyczaj należy po prostu zadeklarować zmienne od najbardziej ogólnego interfejsu, który będzie używany (np
Iterable
,Collection
alboList
) i zainicjować je z realizacją konkretnego (npArrayList
,LinkedList
lubArrays.asList()
).W przeciwnym razie ograniczysz kod do tego konkretnego typu i trudniej będzie go zmienić, kiedy chcesz.
Na przykład, jeśli przekazujesz an
ArrayList
dovoid method(...)
:Innym przykładem byłoby zawsze deklarowanie zmiennej,
InputStream
nawet jeśli zwykle jest to aFileInputStream
lub aBufferedInputStream
, ponieważ pewnego dnia ty lub ktoś inny będzie chciał użyć innego rodzajuInputStream
.źródło
Arrays.asList
jest metodą statyczną. Zobacz docs.oracle.com/javase/1.5.0/docs/guide/language/…Jeśli potrzebujesz prostej listy o rozmiarze 1:
Jeśli potrzebujesz listy kilku obiektów:
źródło
Z Guava możesz pisać:
W Guava są też inne przydatne konstruktory statyczne. Możesz przeczytać o nich tutaj .
źródło
java.util.Arrays
takich, jak:List<String> names = Arrays.asList("Beckah", "Sam", "Michael");
Literały kolekcji nie trafiły do Java 8, ale można użyć interfejsu API Stream do zainicjowania listy w jednym dość długim wierszu:
Jeśli potrzebujesz aby zapewnić, że
List
jestArrayList
:źródło
Z java-9i powyżej, jak zasugerowano w JEP 269: Wygodowe metody fabryczne dla kolekcji , można to osiągnąć za pomocą literałów kolekcji teraz dzięki -
Podobne podejście dotyczyłoby
Map
również -która jest podobna do propozycji literatury kolekcji, jak stwierdził @coobird. Dalsze wyjaśnienia również w JEP -
Alternatywy
Powiązane: Jaki jest sens przeciążonych metod fabryk wygody dla kolekcji w Javie 9
źródło
źródło
Collections.unmodifiableList(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"))
, co staje sięunmodifiableList(asList("Buenos Aires", "Córdoba", "La Plata"))
przy imporcie statycznym. Nie potrzebujesz do tego kolekcji Google.ImmutableList
innym metodomList
, a następnie stracisz tę dokumentację.Możesz stworzyć metodę fabryczną:
Ale to niewiele lepsze niż pierwsze refaktoryzacja.
Dla większej elastyczności może być ogólny:
źródło
W Javie 9 możemy łatwo zainicjować
ArrayList
jedną linię:lub
To nowe podejście do Java 9 ma wiele zalet w stosunku do poprzednich:
Zobacz ten post, aby uzyskać więcej informacji -> Jaka jest różnica między List.of a Arrays.asList?
źródło
Najbardziej kompaktowym sposobem na to jest:
źródło
Po prostu użyj poniższego kodu w następujący sposób.
źródło
Dzięki Eclipse Collections możesz napisać:
Możesz także sprecyzować typy i czy są one zmienne czy niezmienne.
Możesz również zrobić to samo z zestawami i torbami:
Uwaga: jestem osobą odpowiedzialną za kolekcje Eclipse.
źródło
Oto inny sposób:
źródło
(Powinien to być komentarz, ale zbyt długi, więc nowa odpowiedź). Jak wspomnieli inni,
Arrays.asList
metoda ma stały rozmiar, ale to nie jedyny problem. Nie radzi sobie również dobrze z dziedziczeniem. Załóżmy na przykład, że masz:Powyższe powoduje błąd kompilatora, ponieważ
List<B>
(co jest co jest zwracane przez Arrays.asList) nie jest podklasąList<A>
, chociaż można dodawać obiekty typu B doList<A>
obiektu. Aby obejść ten problem, musisz zrobić coś takiego:Jest to prawdopodobnie najlepszy sposób na zrobienie tego, szczególnie. jeśli potrzebujesz nieograniczonej listy lub musisz użyć dziedziczenia.
źródło
Możesz użyć poniższych instrukcji:
Fragment kodu:
źródło
letters = Arrays.asList(new String[]{"A", "B", "C"});
Jak powiedział Tom :
Ale ponieważ narzekałeś na potrzebę ArrayList, powinieneś najpierw wiedzieć, że ArrayList jest podklasą List i możesz po prostu dodać ten wiersz:
Chociaż może to powodować narzekanie na „wydajność”.
W takim przypadku nie ma to dla mnie sensu, ponieważ skoro twoja lista jest predefiniowana, nie została zdefiniowana jako tablica (ponieważ rozmiar jest znany w momencie inicjalizacji). A jeśli to dla ciebie opcja:
Jeśli nie przejmujesz się drobnymi różnicami w wydajności, możesz również bardzo prosto skopiować tablicę do ArrayList:
Okej, ale w przyszłości potrzebujesz czegoś więcej niż tylko nazwy miejsca, potrzebujesz też kodu kraju. Zakładając, że jest to wciąż predefiniowana lista, która nigdy się nie zmieni w czasie wykonywania, wówczas można użyć
enum
zestawu, który wymagałby ponownej kompilacji, gdyby lista musiała zostać zmieniona w przyszłości.stanie się:
Wyliczenia mają
values
metodę statyczną , która zwraca tablicę zawierającą wszystkie wartości wyliczenia w kolejności, w jakiej zostały zadeklarowane, np .:W takim przypadku myślę, że nie potrzebujesz swojej ArrayList.
PS Randyaa zademonstrował inny fajny sposób przy użyciu statycznej metody użytkowej Collections.addAll .
źródło
Java 9 ma następującą metodę utworzenia niezmiennej listy:
który można łatwo dostosować do tworzenia listy zmiennych, jeśli jest to wymagane:
Podobne metody są dostępne dla
Set
iMap
.źródło
źródło
Tak, za pomocą tablic możesz zainicjalizować listę tablic w jednym wierszu,
źródło
Możesz używać
StickyList
z Cactoos :źródło
Spróbuj użyć tej linii kodu:
źródło
W Javie nie możesz tego zrobić
Jak już wspomniano, należy wykonać inicjalizację podwójnego nawiasu klamrowego:
Ale może to zmusić Cię do dodania adnotacji
@SuppressWarnings("serial")
lub wygenerowania seryjnego UUID, co jest denerwujące. Również większość formatatorów kodu rozpakuje to na wiele instrukcji / linii.Alternatywnie możesz to zrobić
ale wtedy możesz chcieć zrobić
@SuppressWarnings("unchecked")
.Również według javadoc powinieneś być w stanie to zrobić:
Ale nie jestem w stanie zmusić go do kompilacji z JDK 1.6.
źródło
Jeśli musisz mieć listę jednego elementu !
Kolekcje pochodzą z pakietu java.util .
źródło
Najlepszy sposób to zrobić:
Wystarczy utworzyć funkcję, która może mieć tyle elementów, ile chcesz i wywołać ją, aby dodać je w jednym wierszu.
źródło
Object
.Oto kod AbacusUtil
Deklaracja : Jestem programistą AbacusUtil.
źródło
Dla mnie Arrays.asList () jest najlepszy i wygodny. Zawsze lubię inicjować w ten sposób. Jeśli jesteś początkującym w kolekcji Java, chciałbym, abyś polecił inicjalizację ArrayList
źródło
add()
metodami?Dlaczego nie zrobić prostej funkcji narzędziowej, która to robi?
„
ll
” oznacza „dosłowną listę”.źródło
co ciekawe, nie wymieniono jednej linijki z drugą metodą przeciążenia
Stream::collect
źródło
W rzeczywistości można to zrobić w jednym wierszu:
źródło