Dari dokumentasi Java 1.6 Collection Framework :
Koleksi yang tidak mendukung operasi modifikasi apa pun (seperti
add
,remove
danclear
) disebut sebagai tidak dapat dimodifikasi . [...] Koleksi yang juga menjamin bahwa tidak ada perubahan pada objek Collection yang akan terlihat disebut sebagai tidak dapat diubah .
Kriteria kedua sedikit membingungkan saya. Mengingat koleksi pertama tidak dapat dimodifikasi, dan dengan asumsi bahwa referensi koleksi asli telah dibuang, apa saja perubahan yang dirujuk pada baris kedua? Apakah ini mengacu pada perubahan elemen yang ada di koleksi, yaitu status elemen?
Pertanyaan kedua:
Agar koleksi tidak dapat diubah, bagaimana cara memberikan jaminan tambahan yang ditentukan? Jika status elemen dalam koleksi diperbarui oleh utas, apakah cukup untuk keabadian bahwa pembaruan dalam keadaan itu tidak terlihat pada utas yang menyimpan koleksi yang tidak bisa diubah?
Agar koleksi tidak dapat diubah, bagaimana cara memberikan jaminan tambahan yang ditentukan?
sumber
newCol = oldCol.add("element")
akan menghasilkan koleksi baru yaitu salinan dari yang lama dengan 1 elemen lagi, dan semua referensi keoldCol
akan tetap mengarah ke koleksi lama yang sama dan tidak berubah.Jawaban:
Koleksi yang tidak dapat dimodifikasi biasanya merupakan tampilan hanya-baca (pembungkus) dari koleksi lain. Anda tidak dapat menambahkan, menghapus, atau menghapusnya, tetapi koleksi yang mendasari dapat berubah.
Koleksi yang tidak dapat diubah tidak dapat diubah sama sekali - mereka tidak membungkus koleksi lain - mereka memiliki elemennya sendiri.
Berikut kutipan dari jambu biji
ImmutableList
Jadi, pada dasarnya, untuk mendapatkan koleksi yang tidak bisa diubah dari yang bisa berubah, Anda harus menyalin elemennya ke koleksi baru, dan melarang semua operasi.
sumber
unmodifiableList
, kode yang hanya menerima referensi ke daftar itu tidak akan dapat mengubahnya, tetapi kode apa pun yang memiliki referensi ke daftar asli dan dapat mengubahnya sebelum pembungkus dibuat akan tetap dapat melakukannya sesudahnya. Jika kode yang membuat daftar asli mengetahui apa yang terjadi pada setiap referensi yang pernah ada, dan mengetahui bahwa tidak ada yang jatuh ke tangan kode yang mungkin mengubah daftar, maka ia dapat mengetahui bahwa daftar tersebut tidak akan pernah ada. diubah. Namun, jika referensi diterima dari kode luar ...unmodifiableList
, atau kode apa pun yang menggunakannya, untuk mengetahui apakah atau bagaimana koleksi yang dibungkus dapat berubah.Perbedaannya adalah Anda tidak dapat memiliki referensi ke koleksi yang tidak dapat diubah yang memungkinkan perubahan. Koleksi yang tidak dapat dimodifikasi tidak dapat dimodifikasi melalui referensi itu , tetapi beberapa objek lain mungkin menunjuk ke data yang sama yang dapat diubahnya.
misalnya
sumber
c1
adalah bisa berubah (yaitu tidak unmodifiable atau berubah ).c2
adalah unmodifiable : tidak dapat diubah sendiri, tetapi jika nanti saya mengubahc1
kemudian bahwa perubahan akan terlihat dalamc2
.Ini karena
c2
ini hanyalah pembungkusc1
dan bukan salinan independen. Guava menyediakanImmutableList
antarmuka dan beberapa implementasi. Mereka bekerja dengan benar-benar membuat salinan input (kecuali jika input adalah koleksi yang tidak dapat diubah sendiri).Mengenai pertanyaan kedua Anda:
Mutabilitas / kekekalan sebuah koleksi tidak bergantung pada mutabilitas / kekekalan objek yang terkandung di dalamnya. Memodifikasi objek yang terdapat dalam koleksi tidak dihitung sebagai "modifikasi koleksi" untuk deskripsi ini. Tentu saja jika Anda membutuhkan koleksi yang tidak dapat diubah, Anda biasanya juga menginginkannya berisi objek yang tidak dapat diubah.
sumber
c1
tidak lolos" bukanlah pertimbangan yang dibedakan di mana pun dalam spesifikasi. Menurut pendapat saya, jika Anda dapat menggunakan koleksi dengan cara yang membuatnya tidak dapat diubah, maka Anda harus selalu menganggapnya tidak dapat diubah.Collection.unmodifiableList()
tidak bisa menjamin itu, karena tidak bisa menjamin argumennya tidak lolos. Jambu bijiImmutableList.of
selalu menghasilkan yang kekalList
, bahkan jika Anda membiarkan argumennya lolos.Sekarang java 9 memiliki Metode pabrik untuk Daftar, Set, Peta, dan Peta yang Tidak Dapat Diubah.
Di Java SE 8 dan versi sebelumnya, Kita dapat menggunakan metode utilitas kelas Koleksi seperti unmodifiableXXX untuk membuat objek Koleksi yang Tidak Dapat Diubah.
Namun metode Collections.unmodifiableXXX ini sangat membosankan dan menggunakan pendekatan verbose. Untuk mengatasi kekurangan tersebut, Oracle corp telah menambahkan beberapa metode utilitas ke antarmuka Daftar, Set, dan Peta.
Sekarang di java 9: - Antarmuka List dan Set memiliki metode "of ()" untuk membuat objek List atau Set yang tidak dapat diubah atau tidak kosong seperti yang ditunjukkan di bawah ini:
Contoh Daftar Kosong
Contoh Daftar Tidak Kosong
sumber
List.copyOf
danSet.copyOf
telah ditambahkan yang memungkinkan membuat salinan daftar / set yang tidak dapat dimodifikasi, atau mengembalikan koleksi yang diberikan jika sudah tidak dapat dimodifikasi, lihat JDK-8191517Saya percaya intinya di sini adalah bahwa meskipun koleksi tidak dapat dimodifikasi, itu tidak memastikan bahwa itu tidak dapat diubah. Ambil contoh koleksi yang menggusur elemen jika sudah terlalu tua. Tidak dapat dimodifikasi hanya berarti bahwa objek yang memegang referensi tidak dapat mengubahnya, bukan tidak dapat diubah. Contoh nyata dari ini adalah
Collections.unmodifiableList
metode. Ini mengembalikan tampilan Daftar yang tidak dapat dimodifikasi. Referensi daftar yang diteruskan ke metode ini masih dapat dimodifikasi sehingga daftar dapat dimodifikasi oleh pemegang referensi yang diteruskan. Hal ini dapat mengakibatkan ConcurrentModificationExceptions dan hal buruk lainnya.Tidak dapat diubah, artinya koleksi tidak dapat diubah dengan cara apa pun.
Pertanyaan kedua: Koleksi yang tidak dapat diubah tidak berarti bahwa objek yang terdapat dalam koleksi tidak akan berubah, hanya saja koleksi tersebut tidak akan berubah dalam jumlah dan komposisi objek yang dimilikinya. Dengan kata lain, daftar referensi koleksi tidak akan berubah. Itu tidak berarti bahwa bagian dalam dari objek yang direferensikan tidak dapat berubah.
sumber
unmodifiableList
dimodifikasi. Jika Anda ingin melakukan ini gunakanImmutableList
.Pure4J mendukung apa yang Anda kejar, dalam dua cara.
Pertama, ini memberikan
@ImmutableValue
anotasi, sehingga Anda dapat membuat anotasi kelas untuk mengatakan bahwa itu tidak dapat diubah. Ada plugin maven untuk memungkinkan Anda memeriksa apakah kode Anda benar-benar tidak dapat diubah (penggunaanfinal
dll.).Kedua, menyediakan koleksi persisten dari Clojure, (dengan generik tambahan) dan memastikan bahwa elemen yang ditambahkan ke koleksi tidak dapat diubah. Performa tersebut rupanya cukup bagus. Semua koleksi tidak dapat diubah, tetapi menerapkan antarmuka koleksi java (dan generik) untuk diperiksa. Mutasi mengembalikan koleksi baru.
Penafian: Saya pengembang ini
sumber