Apakah pesanan dijamin untuk pengembalian kunci dan nilai dari objek LinkedHashMap?

162

Saya tahu LinkedHashMapmemiliki urutan iterasi yang dapat diprediksi (urutan pemasangan). Apakah yang Setdikembalikan oleh LinkedHashMap.keySet()dan Collectiondikembalikan LinkedHashMap.values()juga mempertahankan pesanan ini?

pengguna256239
sumber
1
Karena semua jawaban membahas masalah values()juga keySet(), saya telah memperluas pertanyaan untuk memasukkan itu. Ini berarti lebih banyak pertanyaan dapat ditutup sebagai duplikat dari ini.
Duncan Jones

Jawaban:

226

Antarmuka Peta menyediakan tiga tampilan koleksi , yang memungkinkan konten peta dilihat sebagai satu set kunci, kumpulan nilai, atau set pemetaan nilai kunci. The rangka dari peta didefinisikan sebagai urutan iterator pada pandangan koleksi peta ini kembali elemen mereka. Beberapa implementasi peta, seperti TreeMap kelas, membuat jaminan khusus untuk pesanan mereka; yang lain, seperti HashMapkelas, tidak.

- Peta

Daftar tertaut ini mendefinisikan urutan iterasi, yang biasanya merupakan urutan kunci yang dimasukkan ke dalam peta ( urutan penyisipan ).

- LinkedHashMap

Jadi, ya, keySet(), values(), dan entrySet()(tiga pandangan koleksi disebutkan) kembali nilai-nilai dalam urutan daftar terkait penggunaan internal. Dan ya, JavaDoc untuk Mapdan LinkedHashMapmenjaminnya.

Lagipula itulah inti dari kelas ini.

Powerlord
sumber
8
iterasi atas peta juga dilakukan lebih cepat menggunakan LinkedHashMap daripada HashMap.
Thierry
2
values ​​() mengembalikan koleksi. bukan Daftar. bagaimana cara menyimpannya?
Dejell
7
@Del Collectionhanya kelas dasar untuk nilai apa () kembali. Implementasi dari Koleksi yang dikembalikan masih dikendalikan oleh LinkedHashMap. Dalam LinkedHashMapkasus ini, ia mengembalikan LinkedValuesinstance, kelas privat di dalam LinkedHashMap.java.
Powerlord
2
Keyset LinkedHashMap dalam kasus saya TIDAK dalam urutan yang diwakili dalam peta. Sangat bingung dengan ini.
Amalgovinus
2
Terima kasih telah menautkan ke dokumentasi (dari Map) yang secara eksplisit mengikat urutan peta ke iterator pada tampilan koleksi peta (dan memperjelas apa tampilan koleksi itu). Itu adalah bagian yang hilang untuk saya.
LarsH
11

Melihat sumbernya, sepertinya memang demikian. keySet(),, values()dan entrySet()semua menggunakan iterator entri yang sama secara internal.

merah muda
sumber
1
Akan keren memiliki tautan ke repo, tapi saya malas :-) dan tentu saja, itu bukan jaminan kompatibilitas ke depan.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
6

Jangan bingung LinkedHashMap.keySet()dan LinkedHashMap.entrySet()mengembalikan Set dan karenanya tidak menjamin pemesanan!

Setadalah antarmuka dengan HashSet, TreeSetdll makhluk implementasinya. The HashSetpelaksanaan Setantarmuka tidak menjamin pemesanan. Namun TreeSetdemikian. Juga LinkedHashSettidak.

Oleh karena itu tergantung pada bagaimana Settelah diterapkan LinkedHashMapuntuk mengetahui apakah referensi Set kembali akan menjamin pemesanan atau tidak. Saya membaca kode sumbernya LinkedHashMap, terlihat seperti ini:

private final class KeySet extends AbstractSet<K> {...}
public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {...}

Dengan demikian LinkedHashMap / HashMap memiliki implementasi sendiri Setyaitu KeySet. Jadi jangan bingung dengan ini HashSet.

Juga, urutan dipertahankan oleh bagaimana elemen-elemen dimasukkan ke dalam ember. Lihatlah addEntry(..)metode LinkedHashMapdan membandingkannya dengan HashMapyang menyoroti perbedaan utama antara HashMapdan LinkedHashMap.

anzaan
sumber
4
Meskipun jawaban ini pasti menyajikan informasi yang bermanfaat, itu tidak benar-benar menjawab pertanyaan. Ini pada dasarnya mengatakan bahwa mereka BISA memiliki urutan iterasi yang dapat diprediksi.
Tuupertunut
5

Anda bisa berasumsi begitu. Javadoc mengatakan 'urutan iterasi yang dapat diprediksi', dan satu-satunya iterator yang tersedia di Peta adalah yang untuk keySet (), entrySet (), dan nilai ().

Jadi dengan tidak adanya kualifikasi lebih lanjut itu jelas dimaksudkan untuk berlaku untuk semua iterator tersebut.

Marquis dari Lorne
sumber
0

AFAIK tidak didokumentasikan sehingga Anda tidak dapat "secara formal" menganggapnya demikian. Namun, kecil kemungkinan implementasi saat ini akan berubah.

Jika Anda ingin memastikan pesanan, Anda mungkin ingin mengulangi atas peta yang masuk dan memasukkannya ke dalam set yang diurutkan dengan fungsi pesanan pilihan Anda, meskipun Anda akan membayar biaya kinerja, secara alami.

Uri
sumber
Apakah maksud Anda entrySet () menjamin pesanan, dengan keySet () tidak?
user256239
1
@ kknight: Saya tidak yakin. javadoc menyatakan: "Daftar tertaut ini mendefinisikan urutan iterasi, yang biasanya urutan kunci dimasukkan ke dalam peta (urutan penyisipan).". Namun, JavaDocs untuk JDK sangat ambigu secara umum.
Uri
5
Jika bahkan entrySet () tidak menjamin urutan iterasi, lalu apa perbedaan antara LinkedHashMap dan HashMap? Bagaimana kita bisa mengambil keuntungan dari urutan iterasi yang dapat diprediksi dalam instance LinkedHashMap?
user256239
1
Itu pasti adalah didokumentasikan. Jawabannya sepenuhnya salah.
Marquis of Lorne
-3

Melihat antarmuka itu mengembalikan polos Setdan bukanSortedSet . Jadi tidak ada jaminan.

Sebelum mengasumsikan jaminan implisit dengan melihat implementasi (selalu ide yang buruk) juga melihat implementasi di semua implementasi Java lainnya :)

Anda bisa membuat misalnya TreeSet dengan keySet di konstruktor.

ekstraneon
sumber
3
Melihat lebih dekat pada dokumentasi, memang ada jaminan. Seperti yang sudah ditulis oleh seseorang, itulah inti dari kelas ini.
glglgl
-4

Saya tidak berpikir Anda bisa menganggap pemesanan keySet () dan nilai ().

Saya dapat dengan mudah menulis implementasi LinkedHashMap yang mengembalikan Anda keySet () dan nilai () yang tidak terurut, selama saya tetap menggunakan kontrak dari kedua metode yang didefinisikan dalam Peta, dan diganti di HashMap.

Zoro
sumber
6
Seluruh tujuan LinkedHashMapkelas adalah untuk menjaga urutan elemen saat iterasi peta dan perilaku ini ditentukan dengan baik. Jika Anda menulis subclass tanpa mematuhi spesifikasi kelas dasar, maka Anda melakukan sesuatu yang sangat salah.
zakinster