1. Gambaran keseluruhan
Dalam artikel ini, kita akan meneroka penerapan TreeMap antara muka Peta dari Java Collections Framework (JCF).
TreeMap adalah implementasi peta yang menyimpan catatannya disusun mengikut susunan semula kuncinya atau lebih baik lagi menggunakan pembanding jika disediakan oleh pengguna pada waktu pembinaan.
Sebelum ini, kami telah meliputi HashMap dan LinkedHashMap pelaksanaan dan kita akan sedar bahawa terdapat agak sedikit maklumat tentang bagaimana kelas ini bekerja yang sama.
Artikel yang disebutkan sangat disarankan untuk dibaca sebelum membacanya.
2. Penyusunan Lalai di TreeMap
Secara lalai, TreeMap menyusun semua entri mengikut susunan semula jadi. Untuk bilangan bulat, ini bermaksud tertib menaik dan bagi rentetan, susunan abjad.
Mari lihat urutan semula jadi dalam ujian:
@Test public void givenTreeMap_whenOrdersEntriesNaturally_thenCorrect() { TreeMap map = new TreeMap(); map.put(3, "val"); map.put(2, "val"); map.put(1, "val"); map.put(5, "val"); map.put(4, "val"); assertEquals("[1, 2, 3, 4, 5]", map.keySet().toString()); }
Perhatikan bahawa kami meletakkan kunci bilangan bulat dengan cara yang tidak teratur tetapi semasa mengambil set kunci, kami mengesahkan bahawa kunci tersebut benar-benar dikekalkan dalam urutan menaik. Ini adalah susunan semula jadi bilangan bulat.
Begitu juga, ketika kita menggunakan tali, mereka akan disusun mengikut urutan semula jadi, iaitu mengikut abjad:
@Test public void givenTreeMap_whenOrdersEntriesNaturally_thenCorrect2() { TreeMap map = new TreeMap(); map.put("c", "val"); map.put("b", "val"); map.put("a", "val"); map.put("e", "val"); map.put("d", "val"); assertEquals("[a, b, c, d, e]", map.keySet().toString()); }
TreeMap , tidak seperti peta hash dan peta hash terpaut, tidak menggunakan prinsip hashing di mana sahaja kerana ia tidak menggunakan array untuk menyimpan entri.
3. Penyesuaian Tersuai di TreeMap
Sekiranya kita tidak berpuas hati dengan susunan semula jadi TreeMap , kita juga dapat menentukan peraturan kita sendiri untuk membuat pesanan dengan cara pembanding semasa pembinaan peta pokok.
Dalam contoh di bawah, kami mahu kekunci integer disusun dalam urutan menurun:
@Test public void givenTreeMap_whenOrdersEntriesByComparator_thenCorrect() { TreeMap map = new TreeMap(Comparator.reverseOrder()); map.put(3, "val"); map.put(2, "val"); map.put(1, "val"); map.put(5, "val"); map.put(4, "val"); assertEquals("[5, 4, 3, 2, 1]", map.keySet().toString()); }
Peta hash tidak menjamin urutan kunci yang disimpan dan secara khusus tidak menjamin bahawa pesanan ini akan tetap sama dari masa ke masa, tetapi peta pokok menjamin bahawa kunci akan selalu disusun mengikut urutan yang ditentukan.
4. Kepentingan TreeMap Sorting
Kami sekarang tahu bahawa TreeMap menyimpan semua entri mengikut urutan. Oleh kerana sifat peta pokok ini, kami dapat melakukan pertanyaan seperti; cari "terbesar", cari "terkecil", cari semua kunci kurang dari atau lebih besar daripada nilai tertentu, dll.
Kod di bawah hanya merangkumi sebilangan kecil kes ini:
@Test public void givenTreeMap_whenPerformsQueries_thenCorrect() { TreeMap map = new TreeMap(); map.put(3, "val"); map.put(2, "val"); map.put(1, "val"); map.put(5, "val"); map.put(4, "val"); Integer highestKey = map.lastKey(); Integer lowestKey = map.firstKey(); Set keysLessThan3 = map.headMap(3).keySet(); Set keysGreaterThanEqTo3 = map.tailMap(3).keySet(); assertEquals(new Integer(5), highestKey); assertEquals(new Integer(1), lowestKey); assertEquals("[1, 2]", keysLessThan3.toString()); assertEquals("[3, 4, 5]", keysGreaterThanEqTo3.toString()); }
5. Pelaksanaan Dalaman TreeMap
TreeMap mengimplementasikan antara muka NavigableMap dan mendasarkan dalamannya berdasarkan prinsip pokok hitam-hitam:
public class TreeMap extends AbstractMap implements NavigableMap, Cloneable, java.io.Serializable
Prinsip pokok hitam-merah berada di luar ruang lingkup artikel ini, bagaimanapun, ada perkara penting yang perlu diingat untuk memahami bagaimana ia sesuai dengan TreeMap .
Pertama sekali , pokok merah-hitam adalah struktur data yang terdiri daripada nod; bayangkan sebatang pokok mangga terbalik dengan akarnya di langit dan dahannya tumbuh ke bawah. Akar akan mengandungi unsur pertama yang ditambahkan pada pokok.
Peraturannya adalah bahawa bermula dari akar, setiap elemen di cabang kiri mana-mana simpul selalu kurang daripada elemen dalam simpul itu sendiri. Yang di sebelah kanan selalu lebih hebat. Apa yang menentukan lebih besar atau kurang daripada ditentukan oleh susunan semula jadi unsur-unsur atau pembanding yang ditentukan semasa pembinaan seperti yang kita lihat sebelumnya.
Peraturan ini menjamin bahawa penyertaan peta jalan akan sentiasa dalam keadaan tersusun dan dapat diramalkan.
Kedua , pokok merah-hitam adalah pokok carian binari yang mengimbangkan diri. Atribut ini dan di atas menjamin bahawa operasi asas seperti mencari, mendapatkan, meletakkan dan membuang mengambil masa logaritma O (log n) .
Menjadi keseimbangan diri adalah kunci di sini. Semasa kami terus memasukkan dan menghapus entri, gambarkan pokok tumbuh lebih panjang di satu tepi atau lebih pendek di sisi yang lain.
Ini bermaksud operasi akan memakan masa yang lebih pendek di cawangan yang lebih pendek dan masa yang lebih lama di cawangan yang paling jauh dari akar, sesuatu yang kita tidak mahu berlaku.
Oleh itu, ini dijaga dalam reka bentuk pokok merah-hitam. Untuk setiap penyisipan dan penghapusan, ketinggian maksimum pokok di mana-mana tepi dikekalkan pada O (log n) iaitu pokok mengimbangi dirinya secara berterusan.
Sama seperti peta hash dan peta hash yang dipautkan, peta pohon tidak diselaraskan dan oleh itu peraturan untuk menggunakannya dalam persekitaran berbilang benang serupa dengan yang terdapat dalam dua pelaksanaan peta yang lain.
6. Memilih Peta yang Tepat
Setelah melihat implementasi HashMap dan LinkedHashMap sebelum ini dan sekarang TreeMap , adalah penting untuk membuat perbandingan ringkas antara ketiga untuk membimbing kita yang mana yang sesuai di mana.
Peta hash bagus sebagai pelaksanaan peta tujuan umum yang menyediakan operasi penyimpanan dan pengambilan yang cepat. Namun, ia gagal kerana susunan entri yang huru-hara dan tidak teratur.
Ini menyebabkannya berkinerja buruk dalam senario di mana terdapat banyak lelaran kerana keseluruhan kapasiti array yang mendasari mempengaruhi traversal selain hanya jumlah entri.
Peta hash yang dipautkan mempunyai atribut peta hash yang baik dan menambah pesanan pada entri. Ia berprestasi lebih baik apabila terdapat banyak lelaran kerana hanya jumlah penyertaan yang diambil kira tanpa mengira kapasiti.
Peta pokok memerlukan pesanan ke tahap seterusnya dengan memberikan kawalan sepenuhnya mengenai bagaimana kunci harus disusun. Di sisi lain, ia menawarkan prestasi umum yang lebih buruk daripada dua alternatif lain.
Kita dapat mengatakan peta hash yang dipautkan dapat mengurangi kekacauan dalam penyusunan peta hash tanpa dikenakan penalti prestasi dari peta pohon .
7. Kesimpulannya
Dalam artikel ini, kami telah meneroka kelas Java TreeMap dan pelaksanaan dalamannya. Oleh kerana ini adalah yang terakhir dalam rangkaian implementasi antara muka Peta biasa, kami juga terus membincangkan secara ringkas di mana yang paling sesuai dengan dua yang lain.
Kod sumber lengkap untuk semua contoh yang digunakan dalam artikel ini boleh didapati dalam projek GitHub.