Ik wilde een lijst met opties maken voor testdoeleinden. Eerst deed ik dit:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
Vervolgens heb ik de code als volgt aangepast:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Is er een betere manier om dit te doen?
Antwoord 1, autoriteit 100%
Eigenlijk is waarschijnlijk de “beste” manier om de ArrayList
te initialiseren de methode die je hebt geschreven, omdat er op geen enkele manier een nieuwe List
hoeft te worden gemaakt:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
Het probleem is dat er nogal wat getypt moet worden om naar die List
instantie te verwijzen.
Er zijn alternatieven, zoals het maken van een anonieme binnenklasse met een instantie-initialisatie (ook bekend als een “dubbele accolade-initialisatie”):
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Ik ben echter niet zo dol op die methode, want wat je uiteindelijk krijgt is een subklasse van ArrayList
die een instantie-initialisatiefunctie heeft, en die klasse is gemaakt om slechts één object te maken — dat lijkt me een beetje overdreven.
Het zou leuk geweest zijn als de Collection Literals voorstelvoor Project Coinwerd geaccepteerd (het was gepland om te worden geïntroduceerd in Java 7, maar het is waarschijnlijk ook geen onderdeel van Java 8.):
List<String> list = ["A", "B", "C"];
Helaas zal het je hier niet helpen, omdat het een onveranderlijke List
initialiseert in plaats van een ArrayList
, en bovendien is het nog niet beschikbaar, als het ooit zal gebeuren zijn.
Antwoord 2, autoriteit 98%
Het zou eenvoudiger zijn als je het gewoon zou declareren als een List
– moet het een ArrayList zijn?
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Of als je maar één element hebt:
List<String> places = Collections.singletonList("Buenos Aires");
Dit zou betekenen dat places
onveranderlijkis (proberen dit te wijzigen zal een UnsupportedOperationException
-uitzondering veroorzaken).
Om een veranderlijke lijst te maken die een concrete ArrayList
is, kun je een ArrayList
maken van de onveranderlijke lijst:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Antwoord 3, autoriteit 45%
Het simpele antwoord
Java 10 of hoger:
var strings = List.of("foo", "bar", "baz");
Dit geeft je een onveranderlijkeList
, dus deze kan niet worden gewijzigd.
Dat is wat je wilt in de meeste gevallen waar je het vooraf invult.
Java 9
Als u Java 9gebruikt, kunt u het trefwoord var
niet gebruiken:
List<String> strings = List.of("foo", "bar", "baz");
Java 8 of eerder:
List<String> strings = Arrays.asList("foo", "bar", "baz");
Dit geeft u een List
*ondersteund door een array, zodat deze niet van lengte kan veranderen.
Maar je kunt List.set(...)
aanroepen, dus het is nog steeds wijzigbaar.
*
Implementatiedetail: het is een privé geneste klasse binnen java.util.Arrays
, genaamd ArrayList
,
wat een andere klasse is dan java.util.ArrayList
, ook al zijn hun eenvoudige namen hetzelfde.
Statische import
Je kunt Java 8 Arrays.asList
nog korter maken met een statische import:
import static java.util.Arrays.asList;
...
List<String> strings = asList("foo", "bar", "baz");
Elke moderne IDE*zal dit voor je voorstellen en doen.
Ik raad niet aan om de methode List.of
statisch te importeren als alleen of
, omdat dit verwarrend is.
*
In IntelliJ IDEA drukt u bijvoorbeeld op Alt+Enter
en selecteert u Static import method...
Gebruik Stream
s
Waarom moet het een List
zijn?
Met Java 8 of hoger kunt u een Stream
gebruiken die flexibeler is:
Stream<String> strings = Stream.of("foo", "bar", "baz");
U kunt Stream
s samenvoegen:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
Of je kunt van een Stream
naar een List
gaan:
import static java.util.stream.Collectors.toList;
...
var strings = Stream.of("foo", "bar", "baz").toList(); // Java 16
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList()); // Java 8
Maar gebruik bij voorkeur gewoon de Stream
zonder deze te verzamelen in een List
.
Als u specifiek een java.util.ArrayList
*
nodig heeft
Als u beideeen ArrayList
vooraf wilt invullen endaarna wilt toevoegen, gebruik dan
List<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
of in Java 8 of eerder:
List<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
of met behulp van Stream
:
import static java.util.stream.Collectors.toCollection;
List<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
Maar nogmaals, het is beter om de Stream
gewoon rechtstreeks te gebruiken in plaats van deze te verzamelen in een List
.
*U hebt waarschijnlijk niet specifiek een ArrayList
nodig. Om JEP 269te citeren:
Er is een klein aantalgebruiksscenario’s voor het initialiseren van een veranderlijke verzamelingsinstantie met een vooraf gedefinieerde set waarden. Het heeft meestal de voorkeur om die vooraf gedefinieerde waarden in een onveranderlijke verzameling te hebben en vervolgens de veranderlijke verzameling te initialiseren via een kopieerconstructor.
(nadruk van mij)
Programmeer naar interfaces, niet naar implementaties
Je zei dat je de lijst als een ArrayList
in je code hebt gedeclareerd, maar je moet dat alleen doen als je een lid van ArrayList
gebruikt dat niet in List
.
Wat u waarschijnlijk niet doet.
Gewoonlijk moet u variabelen declareren via de meest algemene interface die u gaat gebruiken (bijv. Iterable
, Collection
of List
) , en initialiseer ze met de specifieke implementatie (bijv. ArrayList
, LinkedList
of Arrays.asList()
).
Anders beperk je je code tot dat specifieke type, en is het moeilijker om te veranderen wanneer je dat wilt.
Als u bijvoorbeeld een ArrayList
doorgeeft aan een void method(...)
:
// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) {
for (String s : strings) { ... }
}
// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
if (!strings.isEmpty()) { strings.stream()... }
}
// List if you also need .get(index):
void method(List<String> strings) {
strings.get(...)
}
// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
??? // You don't want to limit yourself to just ArrayList
}
Een ander voorbeeld is het altijd declareren van een variabele een InputStream
, ook al is het meestal een FileInputStream
of een BufferedInputStream
, omdat u of iemand anders zal een ander soort InputStream
willen gebruiken.
Antwoord 4, autoriteit 5%
Als je een eenvoudige lijst met maat 1 nodig hebt:
List<String> strings = new ArrayList<String>(Collections.singletonList("A"));
Als je een lijst met meerdere objecten nodig hebt:
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
Antwoord 5, autoriteit 3%
Met Guavakun je schrijven:
ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");
In Guava zijn er ook andere nuttige statische constructors. U kunt hiererover lezen.
6, Autoriteit 2%
Collection Literals haalden het niet in Java 8, maar het is mogelijk om de Stream API te gebruiken om een lijst in één vrij lange regel te initialiseren:
List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());
Als u ervoor moet zorgen dat uw List
een ArrayList
is:
ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
7
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
8
U kunt een fabrieksmethode maken:
public static ArrayList<String> createArrayList(String ... elements) {
ArrayList<String> list = new ArrayList<String>();
for (String element : elements) {
list.add(element);
}
return list;
}
....
ArrayList<String> places = createArrayList(
"São Paulo", "Rio de Janeiro", "Brasília");
Maar het is niet veel beter dan je eerste refactoring.
Voor meer flexibiliteit kan het generiek zijn:
public static <T> ArrayList<T> createArrayList(T ... elements) {
ArrayList<T> list = new ArrayList<T>();
for (T element : elements) {
list.add(element);
}
return list;
}
9
In Java 9 kunnen we eenvoudig een ArrayList
in een enkele regel initialiseren:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
of
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
Deze nieuwe benadering van Java 9 heeft veel voordelen ten opzichte van de vorige:
Zie dit bericht voor meer informatie – & GT; Wat is het verschil tussen lijst.van en Arrays.aslist?
10
Over de meest compacte manier om dit te doen is:
Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
11
Gebruik de onderstaande code gewoon als volgt.
List<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Antwoord 12
Met Eclipse Collectionskun je het volgende schrijven:
List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
Je kunt ook specifieker zijn over de typen en of ze veranderlijk of onveranderlijk zijn.
MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Je kunt hetzelfde ook doen met Sets en Tassen:
Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Opmerking:ik ben toegewijd aan Eclipse Collections.
Antwoord 13
Hier is een andere manier:
List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
Antwoord 14
(Zou een reactie moeten zijn, maar te lang, dus nieuwe reactie). Zoals anderen al hebben vermeld, heeft de methode Arrays.asList
een vaste grootte, maar dat is niet het enige probleem ermee. Het gaat ook niet goed om met erfenissen. Stel dat u bijvoorbeeld het volgende heeft:
class A{}
class B extends A{}
public List<A> getAList(){
return Arrays.asList(new B());
}
Het bovenstaande resulteert in een compilerfout, omdat List<B>
(wat wordt geretourneerd door Arrays.asList) geen subklasse is van List<A>
, ook al kunt u objecten van het type B toevoegen aan een List<A>
-object. Om dit te omzeilen, moet je iets doen als:
new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))
Dit is waarschijnlijk de beste manier om dit te doen, in het bijzonder. als u een onbegrensde lijst nodig heeft of overerving moet gebruiken.
Antwoord 15
U kunt de onderstaande verklaringen gebruiken:
Codefragment:
String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);
Antwoord 16
Zoals Tom zei:
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Maar aangezien je klaagde dat je een ArrayList wilde, zou je eerst moeten weten dat ArrayList een subklasse is van List en je zou gewoon deze regel kunnen toevoegen:
ArrayList<String> myPlaces = new ArrayList(places);
Hoewel je daardoor zou kunnen klagen over ‘prestaties’.
In dat geval is het voor mij niet logisch, waarom, aangezien uw lijst vooraf is gedefinieerd, deze niet als een array is gedefinieerd (aangezien de grootte bekend is op het moment van initialisatie). En als dat een optie voor je is:
String[] places = {"Buenos Aires", "Córdoba", "La Plata"};
Als de kleine prestatieverschillen je niet interesseren, kun je ook heel eenvoudig een array naar een ArrayList kopiëren:
ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));
Ok, maar in de toekomst heb je iets meer nodig dan alleen de plaatsnaam, je hebt ook een landcode nodig. Ervan uitgaande dat dit nog steeds een vooraf gedefinieerde lijst is die tijdens runtime nooit zal veranderen, is het passend om een enum
-set te gebruiken, die opnieuw moet worden gecompileerd als de lijst in de toekomst moet worden gewijzigd.
enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}
zou worden:
enum Places {
BUENOS_AIRES("Buenos Aires",123),
CORDOBA("Córdoba",456),
LA_PLATA("La Plata",789);
String name;
int code;
Places(String name, int code) {
this.name=name;
this.code=code;
}
}
Enum’s hebben een statische values
-methode die een array retourneert met alle waarden van de enum in de volgorde waarin ze zijn gedeclareerd, bijvoorbeeld:
for (Places p:Places.values()) {
System.out.printf("The place %s has code %d%n",
p.name, p.code);
}
In dat geval denk ik dat je je ArrayList niet nodig hebt.
P.S. Randyaa demonstreerdenog een leuke manier met behulp van de statische hulpprogramma-methode Collections.addAll.
Antwoord 17
Java 9 heeft de volgende methode om een onveranderlijkelijst te maken:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
die indien nodig gemakkelijk kan worden aangepast om een veranderlijke lijst te maken:
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
Vergelijkbare methoden zijn beschikbaar voor Set
en Map
.
Antwoord 18
List<String> names = Arrays.asList("2","@2234","21","11");
Antwoord 19
Ja, met behulp van Arrays kunt u de arraylijst op één regel initialiseren,
List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
Antwoord 20
Je kunt StickyList
gebruiken van Cactoos:
List<String> names = new StickyList<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
21
Probeer met deze codelijn:
Collections.singletonList(provider)
22
In Java kun je
niet doen
ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Zoals opgemerkt, zou u een initialisatie van dubbele brace moeten doen:
List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};
Maar dit kan je dwingen om een annotatie toe te voegen @SuppressWarnings("serial")
of genereer een seriële UUID die irritant is. Ook de meeste codorme-formatters zullen dat in meerdere verklaringen / regels uitpakken.
Alternatief kunt u
doen
List<String> places = Arrays.asList(new String[] {"x", "y" });
Maar dan wilt u misschien een @SuppressWarnings("unchecked")
.
Ook volgens Javadoc zou u dit moeten doen:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
Maar ik kan het niet krijgen om te compileren met JDK 1.6.
23
Collections.singletonList(messageBody)
Als u een lijst met één artikel nodig hebt!
Collections is van java.util pakket.
Antwoord 24
De beste manier om het te doen:
package main_package;
import java.util.ArrayList;
public class Stackkkk {
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<Object>();
add(list, "1", "2", "3", "4", "5", "6");
System.out.println("I added " + list.size() + " element in one line");
}
public static void add(ArrayList<Object> list,Object...objects){
for(Object object:objects)
list.add(object);
}
}
Maak gewoon een functie die zoveel elementen kan hebben als je wilt en roep deze aan om ze op één regel toe te voegen.
Antwoord 25
Hier is de code van AbacusUtil
// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);
// Or for Immutable List/Set/Map
ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);
// The most efficient way, which is similar with Arrays.asList(...) in JDK.
// but returns a flexible-size list backed by the specified array.
List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");
Verklaring: Ik ben de ontwikkelaar van AbacusUtil.
Antwoord 26
Gebruik Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
is correct. Maar gesprekken naar Arrays.asList()
met nulargumenten of slechts één argument kan worden vervangen door een oproep naar Collections.singletonList()
of Collections.emptyList()
die een geheugen opslaat.
Opmerking: de lijst geretourneerd door Collections.singletonList()
is onveranderlijk, terwijl de lijst Arrays.asList()
heeft aangetroffen, kunt u de methode SET () mogelijk maken. Dit kan de code in zeldzame gevallen breken.
27
voor mij arrays.aslist () is de beste en handige. Ik hou ervan altijd op die manier te initialiseren.
Als u een beginner bent in Java-collecties, dan zou ik willen dat u ArrayList-initialisatie initialiseert
28
Waarom geen eenvoudige nutsfunctie maken die dit doet?
static <A> ArrayList<A> ll(A... a) {
ArrayList l = new ArrayList(a.length);
for (A x : a) l.add(x);
return l;
}
“ll
” staat voor “Literal List”.
ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
29
Interesseerder geen one-liner met de andere overbelasting Stream::collect
-methode wordt vermeld
ArrayList<String> places = Stream.of( "Buenos Aires", "Córdoba", "La Plata" ).collect( ArrayList::new, ArrayList::add, ArrayList::addAll );