Java 9 memperkenalkan metode pabrik baru untuk daftar, List.of
:
List<String> strings = List.of("first", "second");
Apa perbedaan antara opsi sebelumnya dan baru? Artinya, apa perbedaan antara ini:
Arrays.asList(1, 2, 3);
dan ini:
List.of(1, 2, 3);
Jawaban:
Arrays.asList
mengembalikan daftar yang bisa berubah sementara daftar yang dikembalikan oleh tidakList.of
bisa diubah :Arrays.asList
memungkinkan elemen nol sementaraList.of
tidak:contains
berperilaku berbeda dengan nulls:Arrays.asList
mengembalikan tampilan dari larik yang dilewati, sehingga perubahan pada larik juga akan tercermin dalam daftar. KarenaList.of
ini tidak benar:sumber
List.contains(Object o)
javadoc : "Throws [...] NullPointerException - jika elemen yang ditentukan adalah null dan daftar ini tidak mengizinkan elemen null (opsional)". Atau dari pengenalan panjang antarmuka yang hanya sedikit dibaca: "Beberapa implementasi koleksi memiliki batasan pada elemen yang mungkin dikandungnya"List.of
tidak kembali beberapaImmutableList
jenis, nama sebenarnya adalah hanya detail implementasi non-publik. Jika itu publik dan seseorang menayangkannyaList
lagi, di mana bedanya? Di manakah perbedaannyaArrays.asList
, yang mengembalikanList
implementasi non-publik , yang memunculkan pengecualian saat mencobaadd
atauremove
, atau daftar yang dikembalikanCollections.unmodifiableList
yang tidak memungkinkan modifikasi sama sekali? Ini semua tentang kontrak yang ditentukan diList
antarmuka. Antarmuka Koleksi dengan metode opsional selalu OOP tidak murni sejak Java 1.2…Perbedaan antara
Arrays.asList
danList.of
Lihat JavaDocs dan pembicaraan ini oleh Stuart Marks (atau versi sebelumnya).
Saya akan menggunakan yang berikut ini untuk contoh kode:
Kekekalan struktural (Atau: tidak dapat dimodifikasi)
Setiap upaya untuk mengubah struktur
List.of
akan menghasilkan fileUnsupportedOperationException
. Itu termasuk operasi seperti menambah , mengatur , dan menghapus . Namun, Anda dapat mengubah konten objek dalam daftar (jika objek tersebut tidak dapat diubah), sehingga daftar tersebut tidak "sepenuhnya tidak dapat diubah".Ini adalah nasib yang sama untuk daftar yang tidak dapat dimodifikasi yang dibuat dengan
Collections.unmodifiableList
. Hanya daftar ini yang merupakan tampilan dari daftar asli, sehingga dapat berubah jika Anda mengubah daftar aslinya.Arrays.asList
tidak sepenuhnya tidak berubah, tidak ada batasanset
.Demikian pula, mengubah larik pendukung (jika Anda menahannya) akan mengubah daftar.
Kekekalan struktural hadir dengan banyak efek samping yang terkait dengan pengkodean pertahanan, konkurensi, dan keamanan yang berada di luar cakupan jawaban ini.
Permusuhan nol
List.of
dan koleksi apa pun sejak Java 1.5 tidak mengizinkannyanull
sebagai elemen. Mencoba meneruskannull
sebagai elemen atau bahkan pencarian akan menghasilkan fileNullPointerException
.Karena
Arrays.asList
merupakan koleksi dari 1.2 (Collections Framework), memungkinkannull
s.Bentuk berseri
Karena
List.of
telah diperkenalkan di Java 9 dan daftar yang dibuat dengan metode ini memiliki bentuk serialnya sendiri (biner), daftar tersebut tidak dapat dideserialisasi pada versi JDK sebelumnya (tanpa kompatibilitas biner ). Namun, Anda dapat membatalkan / membuat serial dengan JSON, misalnya.Identitas
Arrays.asList
panggilan internalnew ArrayList
, yang menjamin ketidaksetaraan referensi.List.of
tergantung pada implementasi internal. Instans yang dikembalikan dapat memiliki persamaan referensi, tetapi karena ini tidak dijamin, Anda tidak dapat mengandalkannya.Perlu disebutkan bahwa daftar adalah sama (melalui
List.equals
) jika mereka berisi elemen yang sama dalam urutan yang sama, terlepas dari bagaimana mereka dibuat atau operasi apa yang mereka dukung.Implementasi (peringatan: detail dapat berubah seiring versi)
Jika jumlah elemen dalam daftar
List.of
2 atau kurang, elemen disimpan di bidang kelas khusus (internal). Contohnya adalah daftar yang menyimpan 2 elemen (sumber parsial):Jika tidak, mereka disimpan dalam larik dengan cara yang mirip dengan
Arrays.asList
.Efisiensi Ruang dan Waktu
The
List.of
implementasi yang berbasis lapangan (ukuran <2) melakukan sedikit lebih cepat pada beberapa operasi. Sebagai contoh,size()
dapat mengembalikan konstanta tanpa mengambil panjang array, dancontains(E e)
tidak memerlukan overhead iterasi.Membuat daftar yang tidak dapat dimodifikasi melalui
List.of
juga lebih cepat. Bandingkan konstruktor di atas dengan 2 tugas referensi (dan bahkan satu untuk jumlah elemen yang berubah-ubah) keyang membuat 2 daftar ditambah biaya tambahan lainnya. Dalam hal ruang, Anda menghemat
UnmodifiableList
pembungkus ditambah beberapa sen. Pada akhirnya, penghematan yangHashSet
setara lebih meyakinkan.Waktu kesimpulan: gunakan
List.of
ketika Anda menginginkan daftar yang tidak berubah danArrays.asList
ketika Anda menginginkan daftar yang dapat berubah (seperti yang ditunjukkan di atas).sumber
Arrays.asList
tidak sepenuhnya bisa berubah.asList.add(1);
melemparUnsupportedOperationException
.List.of
waktu kapan pun orang ingin meneleponcontains
dan tidak terkejut dengan NullPointerException.Mari kita rangkum perbedaan antara List.of dan Arrays.asList
List.of
dapat digunakan paling baik jika kumpulan data lebih sedikit dan tidak berubah, sementaraArrays.asList
dapat digunakan paling baik jika kumpulan data besar dan dinamis.List.of
mengambil ruang overhead yang sangat sedikit karena memiliki implementasi berbasis lapangan dan mengonsumsi lebih sedikit ruang heap, baik dalam hal overhead tetap dan pada basis per elemen. sementaraArrays.asList
mengambil lebih banyak ruang overhead karena saat inisialisasi, ini membuat lebih banyak objek di heap.Koleksi yang dikembalikan oleh
List.of
tidak dapat diubah dan karenanya aman untuk thread sementara Koleksi yang dikembalikan olehArrays.asList
dapat berubah dan tidak aman untuk thread. (Instans pengumpulan yang tidak dapat diubah umumnya mengkonsumsi lebih sedikit memori daripada rekan mereka yang dapat berubah.)List.of
tidak mengizinkan elemen nol sementaraArrays.asList
memungkinkan elemen nol .sumber
Arrays.asList
versusList.of
, mengingat bahwa yang pertama secara harfiah hanyalah pembungkus di sekitar array. Setidaknya implementasi OpenJDK tampaknya memiliki overhead yang sangat kecil. Faktanya,List.of
perlu membuat salinan dari setiap larik yang diteruskan, jadi kecuali larik itu sendiri akan segera menjadi GC, tampaknya akanList.of
memiliki jejak memori yang jauh lebih besar.List.of(x)
danList.of(x, y)
lebih efisien karena mereka tidak mengalokasikan array sama sekaliList.of
metode tidak diperlukan untuk mengembalikan daftar baru setiap kali. Daftar ini memiliki identitas yang tidak ditentukan, sehingga mungkin ada cache atau deduplikasi atau skalarisasi yang ditangani pada level JVM. Jika tidak dalam versi ini, mungkin di versi berikutnya. Itu diizinkan oleh kontrak. Sebaliknya,Array.asList
bergantung pada identitas larik yang Anda lewati, karena daftar yang dihasilkan adalah tampilan yang bisa berubah pada larik, yang mencerminkan semua perubahan dua arah.Terlepas dari jawaban di atas ada operasi tertentu yang baik
List::of
danArrays::asList
berbeda:Lebih lanjut tentang Koleksi :: singletonList Vs. Daftar
sumber