Saya yakin ada alasan bagus, tetapi bisakah seseorang tolong jelaskan mengapa java.util.Set
antarmuka kurang get(int Index)
, atau get()
metode serupa ?
Tampaknya set itu bagus untuk memasukkan berbagai hal, tetapi saya tidak dapat menemukan cara yang elegan untuk mengambil satu item darinya.
Jika saya tahu saya ingin item pertama, saya bisa menggunakan set.iterator().next()
, tetapi kalau tidak, sepertinya saya harus melemparkan ke Array untuk mengambil item pada indeks tertentu?
Apa cara yang tepat untuk mengambil data dari suatu set? (selain menggunakan iterator)
Saya yakin fakta bahwa itu dikecualikan dari API berarti ada alasan bagus untuk tidak melakukan ini - bisakah seseorang mencerahkan saya?
EDIT: Beberapa jawaban luar biasa di sini, dan beberapa mengatakan "lebih banyak konteks". Skenario spesifik adalah tes dbUnit, di mana saya dapat dengan wajar menyatakan bahwa set yang dikembalikan dari kueri hanya memiliki 1 item, dan saya mencoba mengakses item itu.
Namun, pertanyaannya lebih valid tanpa skenario, karena tetap lebih fokus:
Apa perbedaan antara set dan daftar .
Terima kasih untuk semua jawaban fantastis di bawah ini.
sumber
Jawaban:
Karena set tidak memiliki pemesanan. Beberapa implementasi memang (terutama yang mengimplementasikan
java.util.SortedSet
antarmuka), tetapi itu bukan properti umum set.Jika Anda mencoba menggunakan set dengan cara ini, Anda sebaiknya mempertimbangkan untuk menggunakan daftar.
sumber
Sebenarnya ini adalah pertanyaan berulang ketika menulis aplikasi JavaEE yang menggunakan Pemetaan Objek-Relasional (misalnya dengan Hibernate); dan dari semua orang yang menjawab di sini, Andreas Petersson adalah satu-satunya yang memahami masalah sebenarnya dan menawarkan jawaban yang benar untuk itu: Jawa kehilangan UniqueList! (atau Anda juga dapat menyebutnya OrderedSet, atau IndexedSet).
Maxwing menyebutkan use-case ini (di mana Anda perlu memesan DAN data unik) dan dia menyarankan SortedSet, tapi ini bukan yang benar-benar dibutuhkan Marty Pitt.
"IndexedSet" ini TIDAK sama dengan SortedSet - dalam SortedSet elemen diurutkan dengan menggunakan Comparator (atau menggunakan pemesanan "natural" mereka).
Tetapi sebaliknya lebih dekat ke LinkedHashSet (yang orang lain juga menyarankan), atau bahkan lebih ke "ArrayListSet" (juga tidak ada), karena menjamin bahwa elemen dikembalikan dalam urutan yang sama seperti yang dimasukkan.
Tetapi LinkedHashSet adalah implementasi, bukan antarmuka! Yang diperlukan adalah antarmuka IndexedSet (atau ListSet, atau OrderedSet, atau UniqueList)! Ini akan memungkinkan programmer untuk menentukan bahwa ia membutuhkan kumpulan elemen yang memiliki urutan tertentu dan tanpa duplikat, dan kemudian instantiate dengan implementasi apa pun (misalnya implementasi yang disediakan oleh Hibernate).
Karena JDK adalah open-source, mungkin antarmuka ini akhirnya akan dimasukkan dalam Java 7 ...
sumber
ListOrderedSet
apa yang dibutuhkan OP 7 tahun lalu (dan saya butuhkan hari ini).What is needed is an IndexedSet (or ListSet, or OrderedSet, or UniqueList)...
dan mengabaikan...interface
. Maaf soal itu!Hanya menambahkan satu poin yang tidak disebutkan dalam jawaban mmyers .
Anda juga harus membiasakan diri dengan
SortedSet
antarmuka (implementasi yang paling umum adalahTreeSet
).SortedSet adalah Set (yaitu elemen yang unik) yang disimpan dengan urutan alami elemen atau menggunakan beberapa
Comparator
. Anda dapat dengan mudah mengakses item pertama dan terakhir menggunakanfirst()
danlast()
metode. ASortedSet
sangat berguna sesekali, ketika Anda perlu menjaga koleksi Anda bebas dari duplikat dan dipesan dengan cara tertentu.Sunting : Jika Anda membutuhkan Set yang unsur-unsurnya disimpan dalam urutan penyisipan (seperti Daftar), lihatlah
LinkedHashSet
.sumber
Jenis ini mengarah ke pertanyaan kapan Anda harus menggunakan set dan kapan Anda harus menggunakan daftar. Biasanya, sarannya:
Kasus keempat yang sering muncul adalah Anda tidak membutuhkan keduanya. Dalam hal ini Anda melihat beberapa pemrogram pergi dengan daftar dan beberapa dengan set. Secara pribadi saya merasa sangat berbahaya untuk melihat ditetapkan sebagai daftar tanpa memesan - karena itu benar-benar binatang buas lainnya. Kecuali Anda membutuhkan hal-hal seperti mengatur keunikan atau mengatur kesetaraan, selalu nikmatilah daftar.
sumber
Saya tidak yakin apakah ada yang mengatakannya dengan cara ini, tetapi Anda perlu memahami yang berikut:
Tidak ada elemen "pertama" dalam set.
Karena, seperti yang dikatakan orang lain, set tidak memiliki urutan. Satu set adalah konsep matematika yang secara khusus tidak termasuk pemesanan.
Tentu saja, komputer Anda tidak dapat menyimpan daftar barang yang tidak dipesan dalam memori. Itu harus memiliki beberapa pemesanan. Secara internal itu adalah array atau daftar yang terhubung atau sesuatu. Tetapi Anda tidak benar-benar tahu apa itu, dan tidak benar-benar memiliki elemen pertama; elemen yang keluar "pertama" keluar seperti itu secara kebetulan, dan mungkin bukan yang pertama kali. Bahkan jika Anda mengambil langkah-langkah untuk "menjamin" elemen pertama tertentu, itu masih keluar secara kebetulan, karena Anda kebetulan melakukannya dengan benar untuk satu implementasi tertentu dari Set; implementasi yang berbeda mungkin tidak bekerja seperti itu dengan apa yang Anda lakukan. Dan, pada kenyataannya, Anda mungkin tidak tahu implementasi yang Anda gunakan sebaik yang Anda kira.
Orang-orang mengalami SEMUA ini. ITU. WAKTU. dengan sistem RDBMS dan tidak mengerti. Kueri RDBMS mengembalikan serangkaian catatan. Ini adalah jenis himpunan yang sama dari matematika: koleksi item yang tidak teratur, hanya dalam hal ini item tersebut adalah catatan. Hasil kueri RDBMS sama sekali tidak memiliki jaminan pesanan kecuali Anda menggunakan klausa ORDER BY, tetapi setiap saat orang menganggapnya dan kemudian naik sendiri suatu hari ketika bentuk data atau kode mereka sedikit berubah dan memicu pengoptimal permintaan untuk bekerja dengan cara yang berbeda dan tiba-tiba hasilnya tidak keluar dalam urutan yang mereka harapkan. Ini biasanya adalah orang-orang yang tidak memperhatikan di kelas basis data (atau ketika membaca dokumentasi atau tutorial) ketika dijelaskan kepada mereka, di muka, bahwa hasil permintaan tidak memiliki pemesanan yang dijamin.
sumber
Set
ituIterable
.beberapa struktur data hilang dari koleksi java standar.
Tas (seperti set tetapi dapat mengandung elemen beberapa kali)
UniqueList (daftar berurutan, dapat memuat setiap elemen hanya satu kali)
Sepertinya Anda perlu uniquelist dalam hal ini
jika Anda membutuhkan struktur data yang fleksibel, Anda mungkin tertarik dengan Google Collections
sumber
Itu benar, elemen di Set tidak diurutkan, menurut definisi Set Collection. Jadi mereka tidak dapat diakses oleh indeks.
Tetapi mengapa kita tidak memiliki metode get (objek), bukan dengan memberikan indeks sebagai parameter, tetapi objek yang sama dengan yang kita cari? Dengan cara ini, kita dapat mengakses data elemen di dalam Set, hanya dengan mengetahui atributnya yang digunakan oleh metode yang sama.
sumber
Jika Anda akan melakukan banyak akses acak dengan indeks dalam satu set, Anda bisa mendapatkan tampilan array dari elemen-elemennya:
Ada dua kelemahan utama:
sumber
Itu karena Set hanya menjamin keunikan, tetapi tidak mengatakan apa pun tentang akses optimal atau pola penggunaan. Yaitu, Set dapat berupa Daftar atau Peta, yang masing-masing memiliki karakteristik pengambilan yang sangat berbeda.
sumber
Satu-satunya alasan saya bisa memikirkan untuk menggunakan indeks numerik dalam set adalah untuk iterasi. Untuk itu, gunakan
sumber
Saya mengalami situasi di mana saya benar-benar ingin diurutkan Set dengan akses melalui indeks (saya setuju dengan poster lain yang mengakses Set yang tidak disortir dengan indeks tidak masuk akal). Contohnya adalah pohon di mana saya ingin anak-anak disortir dan duplikat anak-anak tidak diizinkan.
Saya membutuhkan akses melalui indeks untuk menampilkannya dan atribut yang ditetapkan berguna untuk secara efisien menghilangkan duplikat.
Tidak menemukan koleksi yang cocok di koleksi java.util atau google, saya merasa mudah untuk mengimplementasikannya sendiri. Ide dasarnya adalah untuk membungkus SortedSet dan membuat Daftar ketika akses melalui indeks diperlukan (dan lupakan daftar ketika SortedSet diubah). Ini tentu saja hanya bekerja secara efisien ketika mengubah SortedSet yang dibungkus dan mengakses daftar dipisahkan dalam masa koleksi. Kalau tidak, ia berperilaku seperti daftar yang sering diurutkan, yaitu terlalu lambat.
Dengan sejumlah besar anak-anak, kinerja ini jauh lebih baik daripada daftar yang saya simpan diurutkan melalui Collections.sort.
sumber
Harap dicatat hanya 2 struktur data dasar yang dapat diakses melalui indeks.
O(1)
kompleksitas waktu yang harus dicapaiget(int index)
operasi.O(n)
kompleksitas waktu untuk mencapaiget(int index)
operasi.Di Jawa,
ArrayList
diimplementasikan menggunakan struktur data Array .Sementara Set struktur data biasanya dapat diimplementasikan melalui HashTable / HashMap atau BalancedTree struktur data, untuk cepat mendeteksi apakah sebuah elemen ada dan menambahkan non-ada elemen, biasanya diterapkan dengan baik Set dapat mencapai
O(1)
waktu kompleksitascontains
operasi. Di Jawa,HashSet
adalah implementasi Set yang paling umum digunakan , diimplementasikan dengan memanggilHashMap
API, danHashMap
diimplementasikan menggunakan rantai terpisah dengan daftar tertaut (kombinasi dari Array dan LinkedList ).Karena Set dapat diimplementasikan melalui struktur data yang berbeda, tidak ada
get(int index)
metode untuk itu.sumber
Data.Sequence.lookup
fungsi Haskell ) juga memungkinkan akses melalui indeks (O(1)
dekat ujungnyaO(log n)
dekat tengah, lebih akuratO(min(log(k), log(n-k)))
), juga pohon biner melakukannya juga (LihatData.Set.lookupIndex
fungsi Haskell ). Jadi pernyataan awal Anda bahwa "Harap dicatat hanya 2 struktur data dasar yang dapat diakses melalui indeks" tidak benar.Alasan mengapa antarmuka Set tidak memiliki panggilan tipe indeks atau bahkan sesuatu yang lebih mendasar, seperti first () atau last (), adalah karena ia merupakan operasi yang ambigu, dan karenanya merupakan operasi yang berpotensi berbahaya. Jika suatu metode mengembalikan Set, dan Anda memanggil, katakan metode first () di atasnya, apa hasil yang diharapkan, mengingat bahwa Set generik tidak membuat jaminan pada pemesanan? Objek yang dihasilkan bisa sangat bervariasi antara setiap panggilan metode, atau mungkin tidak dan membuai Anda ke rasa aman yang salah, sampai perpustakaan Anda menggunakan perubahan mengubah implementasi di bawahnya dan sekarang Anda menemukan bahwa semua kode Anda istirahat untuk tidak ada alasan khusus.
Saran tentang pemecahan masalah yang tercantum di sini bagus. Jika Anda memerlukan akses yang diindeks, gunakan daftar. Berhati-hatilah dengan menggunakan iterator atau toArray dengan Perangkat generik, karena a) tidak ada jaminan pada pemesanan dan b) tidak ada jaminan bahwa pemesanan tidak akan berubah dengan pemanggilan berikutnya atau dengan implementasi mendasar yang berbeda. Jika Anda membutuhkan sesuatu di antaranya, SortedSet atau LinkedHashSet adalah yang Anda inginkan.
// Aku berharap antarmuka Set memiliki elemen get-random.
sumber
java.util.Set
adalah koleksi barang yang tidak dipesan. Tidak masuk akal jika Set memiliki get (int index), karena Set tidak memiliki indeks dan Anda hanya bisa menebak nilainya.Jika Anda benar-benar menginginkan ini, kode metode untuk mendapatkan elemen acak dari Set.
sumber
Anda dapat melakukan
new ArrayList<T>(set).get(index)
sumber
new ArrayList<T>(t).get(0)
Saya pikir ada oposisi yang valid terhadap gagasan untuk mendapatkan elemen tertentu dari Set oleh indeks. Tapi alangkah baiknya jika Set memiliki fungsi anggota only () yang, untuk Set ukuran 1, memberikan akses mudah ke satu-satunya elemen dalam Set. Ini akan menyelamatkan yang disebutkan di atasnew ArrayList
ataufor (Foo foo : foos) { return foo; }
Jika Anda tidak keberatan set akan diurutkan maka Anda mungkin tertarik untuk melihat indeks-pohon-peta .
TreeSet / TreeMap yang disempurnakan menyediakan akses ke elemen dengan indeks atau mendapatkan indeks suatu elemen. Dan implementasinya didasarkan pada pembaruan bobot simpul di pohon RB. Jadi tidak ada iterasi atau cadangan dengan daftar di sini.
sumber
Set adalah antarmuka dan beberapa kelas implementasinya adalah HashSet, TreeSet dan LinkedHashSet. Ini menggunakan HashMap di bawah tenda untuk menyimpan nilai. Karena HashMap tidak mempertahankan pesanan, tidak mungkin untuk mendapatkan nilai berdasarkan indeks.
Anda sekarang harus berpikir bagaimana Set menggunakan HashMap karena HashMap menyimpan pasangan kunci, nilai tetapi Set tidak. pertanyaan yang valid. ketika Anda menambahkan elemen di Set, secara internal, ia mempertahankan HashMap di mana kuncinya adalah elemen yang ingin Anda masukkan di Set dan nilainya adalah konstanta dummy. Di bawah ini adalah implementasi internal fungsi add. Karenanya, semua kunci di HashMap akan memiliki nilai konstan yang sama.
sumber
Set
implementasi digunakan diHashMap
bawah tenda untuk menyimpan nilai, dapatkah Anda membuktikan klaim ituTreeSet
?the keys in the HashMap will have the same constant value
kunci diHashMap
akan memetakan ke satu dan sama abadiObject
Untuk mendapatkan elemen dalam Set, saya menggunakan yang berikut:
sumber
T
didefinisikan? Mengapaif (true)
?