Pertanyaan Inisialisasi ArrayList dalam satu baris


Saya ingin membuat daftar opsi untuk tujuan pengujian. Pada awalnya, saya melakukan ini:

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

Lalu saya refactor kode sebagai berikut:

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

Apakah ada cara yang lebih baik untuk melakukan ini?


2157
2018-06-17 04:10


asal


Jawaban:


Sebenarnya, mungkin cara "terbaik" untuk menginisialisasi ArrayList adalah metode yang Anda tulis, karena tidak perlu membuat yang baru List dengan cara apapun:

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

Yang menarik adalah bahwa ada sedikit pengetikan yang diperlukan untuk merujuk itu list contoh.

Ada beberapa alternatif, seperti membuat kelas dalam anonim dengan penginisialisasi instance (juga dikenal sebagai "inisialisasi penjepit ganda"):

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

Namun, saya tidak terlalu menyukai metode itu karena apa yang Anda akhirnya adalah subclass dari ArrayList yang memiliki penginisialisasi instance, dan kelas tersebut dibuat hanya untuk membuat satu objek - yang sepertinya sedikit berlebihan bagi saya.

Apa yang akan menyenangkan adalah jika Koleksi proposal Literal untuk Koin Proyek diterima (itu dijadwalkan akan diperkenalkan di Java 7, tetapi itu tidak mungkin menjadi bagian dari Java 8 baik.):

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

Sayangnya itu tidak akan membantu Anda di sini, karena akan menginisialisasi yang tidak dapat diubah List bukan sebuah ArrayList, dan lebih jauh lagi, itu belum tersedia, jika itu akan terjadi.


1624
2018-06-17 04:13



Akan lebih sederhana jika Anda hanya mendeklarasikannya sebagai List - Apakah itu harus menjadi ArrayList?

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

Atau jika Anda hanya memiliki satu elemen:

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

Ini artinya itu places aku s kekal (mencoba mengubahnya akan menyebabkan UnsupportedOperationException pengecualian untuk dilemparkan).

Untuk membuat daftar yang bisa berubah yang konkrit ArrayList Anda dapat membuat ArrayList dari daftar yang tidak dapat diubah:

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

1725
2018-06-17 04:15



Jawaban sederhana

Di Java 8 atau sebelumnya:

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

Ini akan memberi Anda List didukung oleh array, sehingga tidak dapat mengubah panjang.
Tetapi Anda bisa menelepon List.set, jadi masih bisa berubah.


Di Java 9:

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

Ini akan memberi Anda yang abadi List, jadi itu tidak bisa diubah.
Apa yang Anda inginkan dalam banyak kasus di mana Anda mengisi itu.


Jawaban yang lebih singkat

Anda bisa membuatnya Arrays.asList bahkan lebih pendek dengan impor statis:

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

Impor statis:

import static java.util.Arrays.asList;  

Yang IDE modern akan menyarankan dan secara otomatis lakukan untuk Anda.
Misalnya di IntelliJ IDEA Anda menekan Alt+Enter dan pilih Static import method....


Namun, saya tidak menyarankan memperpendek Java 9 List.of metode, karena baru saja of menjadi membingungkan.
List.of sudah cukup pendek dan membaca dengan baik.


Menggunakan Streams

Kenapa harus menjadi List?
Dengan Java 8 atau yang lebih baru, Anda dapat menggunakan Stream yang lebih fleksibel:

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

Anda dapat menggabungkan Streams:

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

Atau Anda dapat beralih dari Stream ke a List:

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

Tetapi sebaiknya, gunakan saja Stream tanpa mengumpulkannya ke a List.


Jika kamu sangat khusus membutuhkan java.util.ArrayList

(Kamu mungkin tidak.)
Kutipan JEP 269 (penekanan saya):

Ada sebuah set kecil kasus penggunaan untuk menginisialisasi instance koleksi yang bisa berubah dengan kumpulan nilai yang telah ditentukan sebelumnya. Biasanya lebih baik untuk memiliki nilai-nilai yang telah ditetapkan dalam koleksi abadi, dan kemudian menginisialisasi koleksi bisa berubah melalui konstruktor salinan.


Jika Anda menghendaki kedua prepopulate an ArrayList  dan tambahkan setelah itu (mengapa?), gunakan

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

atau di Java 9:

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

atau menggunakan Stream:

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

Tetapi sekali lagi, lebih baik gunakan saja Stream langsung alih-alih mengumpulkannya ke a List.


Program ke antarmuka, bukan ke implementasi

Anda mengatakan Anda telah mendeklarasikan daftar sebagai ArrayList dalam kode Anda, tetapi Anda seharusnya hanya melakukan itu jika Anda menggunakan beberapa anggota ArrayList itu tidak ada List.

Yang kemungkinan besar tidak Anda lakukan.

Biasanya Anda hanya perlu mendeklarasikan variabel dengan antarmuka paling umum yang akan Anda gunakan (mis. Iterable, Collection, atau List), dan menginisialisasi mereka dengan implementasi spesifik (mis. ArrayList, LinkedList atau Arrays.asList()).

Kalau tidak, Anda membatasi kode Anda untuk jenis tertentu, dan itu akan lebih sulit untuk diubah ketika Anda ingin.

Sebagai contoh:

// 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

Contoh lain akan selalu mendeklarasikan variabel an InputStream meskipun biasanya a FileInputStream atau a BufferedInputStream, karena suatu hari nanti Anda atau orang lain akan ingin menggunakan jenis lain InputStream.


580
2017-09-09 12:33



Jika Anda membutuhkan daftar sederhana ukuran 1:

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

Jika Anda memerlukan daftar beberapa objek:

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

100
2017-08-30 04:33



Dengan Jambu biji kamu bisa menulis:

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

Di Guava ada juga konstruktor statis berguna lainnya. Anda dapat membaca tentang mereka sini.


52
2017-07-29 13:24



Koleksi literal tidak membuatnya menjadi Java 8, tetapi mungkin untuk menggunakan Stream API untuk menginisialisasi daftar dalam satu baris yang agak panjang:

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

Jika Anda perlu memastikan bahwa Anda List adalah 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