Soru Bir ArrayList'in bir satırda başlatılması


Test amaçlı bir seçenekler listesi oluşturmak istiyorum. İlk önce şunu yaptım:

ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

Sonra kodu şu şekilde yeniden kodlandırdım:

ArrayList<String> places = new ArrayList<String>(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

Bunu yapmanın daha iyi bir yolu var mı?


2164
2018-06-17 04:10


Menşei


Bu, ünite testi için amaçlanmışsa, bir salıncak için dışarı çıkmayı deneyin. Java kodunu test ederken test kodunuzu yazabilirsiniz ve ArrasyList<String> places = ["Buenos Aires", "Córdoba", "La Plata"] - ripper234
Java SE 7'de, yapılandırıcının parametrelenmiş tipini boş bir tip parametresi (<>) ile değiştirebilirsiniz: Harita <String, Liste <String >> myMap = yeni HashMap <> (); - Rose
Ayrıca bakınız stackoverflow.com/questions/157944/create-arraylist-from-array - Christoffer Hammarström
çift ​​canlandırma başlatmayı kullanın :) - Mohammad Reza Khatami
Stream.of ("val1", "val2") toplayın (Collectors.toList ()); // ArrayList, Java8 çözümünü oluşturur. - torina


Cevaplar:


Aslında, muhtemelen başlatmak için "en iyi" yolu ArrayList yeni oluşturmanıza gerek olmadığı için yazdığınız yöntemdir List her şekilde:

ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");

Yakalama, buna değinmek için biraz yazarak yazmak zorundadır. list örneği.

Örnek başlatıcı ile anonim bir iç sınıf oluşturma gibi alternatifler de vardır ("çift kaşlı başlatma" olarak da bilinir):

ArrayList<String> list = new ArrayList<String>() {{
    add("A");
    add("B");
    add("C");
}};

Ancak, bu yönteme çok düşmüyorum çünkü sonuçta ortaya çıkan şey bir alt sınıftır. ArrayList Bir örnek başlatıcıya sahip olan ve bu sınıf sadece bir nesne oluşturmak için yaratıldı - sadece bana biraz fazla gibi görünüyor.

Güzel olurdu ne olurdu Koleksiyon Yazıları teklifi için Proje madeni para kabul edildi (Java 7'de tanıtılmak istenmişti, ancak Java 8'in bir parçası da olmadı.):

List<String> list = ["A", "B", "C"];

Ne yazık ki, bir immutable'ı başlatacağından, burada size yardımcı olmayacaktır. List bir değil ArrayListve dahası, eğer mevcutsa, henüz mevcut değildir.


1627
2018-06-17 04:13



Görmek stackoverflow.com/questions/924285 çift-brace başlatma, artıları ve eksileri hakkında daha fazla bilgi için. - Eddie
@Eddie: Link için iyi bir çağrı - çift-brace başlatma üzerinde bir cümle tam olarak tanımlamak için yeterli değildir. - coobird
Yalnızca Otomatik kutu listesine <Double> list = [1.0, 2.0, 3.0] güvenmiyorsanız çalışır; başarısız olur. - Richard B
Şey, sadece göstermeye gidiyor - bir adamın sözdizimsel şeker başka bir sözdizimsel diyabet olduğunu. Bu 'alternatiflerden' uzak duracağım. - corsiKa
Bu cevap, en çok konuşulan ve bahsettiğimiz Project Coin olduğundan, bu java 9'un List.of (...) sözdizimi ile birlikte gönderilmesi gerektiğini düşünürüm: docs.oracle.com/javase/9/docs/api/java/util/List.html#of-E...- - Asaf


Sadece bir deklarasyon olarak ilan ederseniz daha basit olurdu List - ArrayList olmak zorunda mı?

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

Ya da sadece tek bir öğeniz varsa:

List<String> places = Collections.singletonList("Buenos Aires");

Bu demek oluyor ki places olduğu değişmez (değiştirmeye çalışmak, UnsupportedOperationException atılacak istisna).

Beton olan değişken bir liste yapmak ArrayList bir tane oluşturabilirsiniz ArrayList değişmez listeden:

ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

1734
2018-06-17 04:15



@Marcase: Sınıfınızı ArrayList yerine bir Liste kullanacak şekilde değiştiremez misiniz? - Lawrence Dol
Cevabım gereğince, ArrayListbildirimi değiştirmek için daha iyi bir tasarım olurdu List. Arabirimleri belirtin, uygulamaları değil. - Christoffer Hammarström
@Christoffer Hammarström: beyanı Liste ve kullanır Liste <String> places = Arrays.asList (...); o kullanamayacak places.add ( "blabla") - maks
Sadece açık olmak gerekirse, asList(...) sabit bir boyut döndürür List bu mutasyona benzer operasyonlarda patlar remove ve clear, şeyler List sözleşmeyi destekleme iddiaları. Beyanı bırakmış olsanız bile List, kullanman gerek List l = new ArrayList(asList(...)) OperationNotSupported istisnalarını atmayan bir nesne elde etmek için. Liskov İkame İlkesi kim? - Splash
@Sıçrama: remove ve clear isteğe bağlı işlemler List, yani asList(...) sözleşmeyi takip eder. OP hiçbir yerde sonradan daha fazla eleman eklemeyi gerekli görmüyor, örnek sadece bir List Bu üç element ile başlatılması gerekiyor. - Christoffer Hammarström


Basit cevap

Java 8'de veya daha eski sürümlerde:

List<String> strings = Arrays.asList("foo", "bar", "baz");

Bu size bir List dizi tarafından desteklenen, bu yüzden uzunluk değiştiremezsiniz.
Ama sen arayabilirsin List.setbu yüzden hala değişebilir.


Java 9'da:

List<String> strings = List.of("foo", "bar", "baz");

Bu size bir değişmez verecektir ListYani değiştirilemez.
Çoğu durumda, hangisini tercih ediyorsun?


Daha kısa cevap

Yapabilirsin Arrays.asList statik bir içe aktarma ile daha kısa:

List<String> strings = asList("foo", "bar", "baz");

Statik ithalat:

import static java.util.Arrays.asList;  

Herhangi bir modern IDE sizin için önerecek ve otomatik olarak sizin için yapacak.
Örneğin IntelliJ IDEA’da Alt+Enter ve seç Static import method....


Ancak, Java'yı kısaltmanızı önermiyorum 9 List.of yöntem, çünkü sadece sahip olmak of kafa karıştırıcı olur.
List.of zaten yeterince kısa ve iyi okur.


kullanma Streams

Neden olmak zorunda List?
Java 8 veya daha sonra bir Stream daha esnek olan:

Stream<String> strings = Stream.of("foo", "bar", "baz");

Sen birleştirebilirsin Streams:

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

Ya da Stream bir List:

List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());

Ama tercihen, sadece Stream onu toplamaksızın List.


Eğer sen Gerçekten mi özellikle bir java.util.ArrayList

(Muhtemelen yapmazsın.)
Alıntılamak JEP 269 (vurgu benim):

Var küçük set Önceden tanımlanmış bir değerler seti ile bir değişken koleksiyon örneğinin başlatılması için kullanım durumları. Bu önceden tanımlanmış değerlerin immutable bir koleksiyonda olması ve daha sonra bir kopya kurucu vasıtasıyla değiştirilebilen koleksiyonun başlatılması tercih edilir.


Eğer istersen her ikisi de prepopulate bir ArrayList  ve sonradan ekle (neden?), kullan

List<String> strings = new ArrayList<>(asList("foo", "bar", "baz"));

veya Java 9'da:

List<String> strings = new ArrayList<>(List.of("foo", "bar", "baz"));

veya kullanarak Stream:

List<String> strings = Stream.of("foo", "bar", "baz")
                             .collect(toCollection(ArrayList::new));

Ama yine de, sadece kullanmak Stream doğrudan onu toplamak yerine List.


Programlara değil arayüzlere program

Listeyi bir ilan olarak ilan ettin. ArrayList kodunuzda, ancak yalnızca bazı üyelerini kullanıyorsanız ArrayList içinde değil List.

Muhtemelen yapmıyorsun.

Genellikle, değişkenleri yalnızca kullanacağınız genel arayüze göre bildirmelisiniz (ör. Iterable, Collectionveya List) ve bunları spesifik uygulama ile başlatabilir (ör. ArrayList, LinkedList veya Arrays.asList()).

Aksi halde kodunuzu bu tür bir türe sınırlandırıyorsunuz ve istediğiniz zaman değiştirmek zorlaşıyor.

Örneğin:

// Iterable if you just need iteration, for (String s : strings):
Iterable<String> strings = new ArrayList<>();   

// Collection if you also need .size() or .stream():
Collection<String> strings = new ArrayList<>(); 

// List if you also need .get(index):
List<String> strings = new ArrayList<>();       

// Don't declare a specific list implementation
// unless you're sure you need it:
ArrayList<String> strings = new ArrayList<>();  // You don't need ArrayList

Başka bir örnek her zaman değişken beyanıdır. InputStream genellikle olsa bile FileInputStream ya da BufferedInputStreamçünkü bir gün yakında siz ya da başka biri başka bir çeşit kullanmak isteyecektir InputStream.


582
2017-09-09 12:33



Çok teşekkür ederim. Kodumda 'statik' içe aktarmayı çıkarmayı denedim, ancak derleyicinin hiçbiri olmayacaktı. Kodun çalışması için neden statik gereklidir? - jollyroger
@korsan bayrağı: Arrays.asList statik bir yöntemdir. Görmek docs.oracle.com/javase/1.5.0/docs/guide/language/... - Christoffer Hammarström
@ ChristofferHammarström Bu durumda, acemi aklım bana statik ithalatın küresel değişkenlere ve bu tür kullanımla ilgili tehlikelere çok benzediğini söyler. Bu varsayım doğru mu ve aynı cevabın da daha fazla oy almanın üstünde mi? - jollyroger
Statik içe aktarımı istemiyorsanız, statik asList yönteminin tam yolunu da tanımlayabilirsiniz, böylece: <String> string = java.util.Arrays.asList ("", ""); - Geert Weening
Ya da import java.util.Arrays'i kullanabilirsiniz; ve Arrays.asList ("", ""); Statik bir içe aktarma kullanmanız gerekmez. Tam bir yol kullanmanız gerekmiyor. Statik yöntemler ithalatı önemsemiyor. Onları bulmak için bir örnek kullanırsanız rahatsız olurlar. - candied_orange


1 numaralı basit bir listeye ihtiyacınız varsa:

List<String> strings = new ArrayList<String>(Collections.singletonList("A"));

Birkaç nesnenin bir listesine ihtiyacınız varsa:

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");

100
2017-08-30 04:33





İle Guava Yazabilirsin:

ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

Guava'da başka kullanışlı statik kurucular da vardır. Onlar hakkında okuyabilirsiniz İşte.


52
2017-07-29 13:24



Eminim ki bunu sadece java.util.Arrays gibi, List<String> names = Arrays.asList("Beckah", "Sam", "Michael"); - beckah
@beckah yöntemi Arrays.asLists, ArrayList oluşturmayla ilgili iken, Type List nesnesini oluşturur. - Paweł Adamski
Bu yöntem aslında çok yararlı değildir ve ileride kullanımdan kaldırılacaktır. - shmosel


Koleksiyon hazırlıkları onu Java 8'e dönüştürmedi, ancak bir listeyi oldukça uzun bir satırda başlatmak için Stream API'sini kullanmak mümkün:

List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());

Eğer emin olmanız gerekiyorsa List bir ArrayList:

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));

32
2018-04-03 23:21





import com.google.common.collect.ImmutableList;

....

List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");

26
2018-05-12 13:14



Bunu yapmak için yeni bir bağımlılık eklemek istemiyorum. - Macarse
Bu aynı Collections.unmodifiableList(Arrays.asList("Buenos Aires", "Córdoba", "La Plata")), olur unmodifiableList(asList("Buenos Aires", "Córdoba", "La Plata")) statik ithalat ile. Bunun için Google Koleksiyonlarına ihtiyacınız yok. - Christoffer Hammarström
Hayır, aynı değil. ImmutableList, değiştirilemediğinde, sonuç türünde değişmezliğini belgelediği için, bunu normal bir Liste olarak maskeler. - David Pierre
Değişmez olanın yerine, google koleksiyonları ayrıca düzenlenebilir dizi listesi sunar: Liste <String> = Lists.newArrayList ("Buenos Aires", "Córdoba", "La Plata"); - L. Holanda
Bunu geçeceksin ImmutableList almak başka yöntemlere Listve sonra yine de bu belgeleri kaybettin. - Christoffer Hammarström


Bir fabrika yöntemi oluşturabilirsiniz:

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");

Ama bu ilk refakatçınızdan çok daha iyi değil.

Daha fazla esneklik için jenerik olabilir:

public static <T> ArrayList<T> createArrayList(T ... elements) {
  ArrayList<T> list = new ArrayList<T>();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}

22
2018-05-04 00:57



Orijinal gönderiye geri dönün, dizinin başlatılmasını istiyor Tek çizgi7 ek satır değil. - L. Holanda
@LeoHolanda: Her küçük şey için fabrika yöntemleri oluşturmak çok fazla katılıyorum. Fakat bağlı Durumda, ve bu yöntemin kullanılacağı zaman sayısı, onu oluşturmak için mantıklı olabilir. Ek soyutlama katmanları oluşturmak için Kaldır karmaşıklık, daha fazla oluşturarak anlamlı yakalayan yöntemleri niyet tasarımcının - Jordão


İle Java 9, önerildiği gibi JDK Geliştirme Önerisi - 269, bu kullanılarak elde edilebilir koleksiyon edebi şimdiki gibi -

List<String> list = List.of("A", "B", "C");

Set<String> set = Set.of("A", "B", "C");

Ayrıca benzer bir yaklaşım Map de -

Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")

benzer Koleksiyon Yazıları teklifi @coobird tarafından da belirtildiği gibi. Ayrıca JEP belgesinde de açıklığa kavuşturuldu -


Alternatifler

Dil değişiklikleri birkaç kez dikkate alındı ​​ve reddedildi:

Proje Para Önerisi, 29 Mart 2009 

Proje Para Önerisi, 30 Mart 2009 

JEP 186, lambda-dev, Ocak-Mart 2014 tartışması

Dil   teklifler, kütüphane tabanlı bir öneri olarak tercih edildi.   bu şekilde özetlendi mesaj.

Zincirli aynı şeyi oku ~> Aşırı Yüklenmiş Fabrikası Yöntemlerinin Noktası Nedir?


17
2018-02-02 17:36





Java 9'da kolayca bir başlangıç ​​yapabiliriz ArrayList tek bir satırda:

List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");

veya

List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));

Java 9'un bu yeni yaklaşımı, öncekilere göre birçok avantajı var:

  1. Uzay verimliliği
  2. Değişmezlik
  3. İş parçacığı güvenli

Daha fazla bilgi için bu gönderiye bakın -> List.of ve Arrays.asList arasındaki fark nedir?


11
2017-10-06 01:16