―hashmap -
ข้อดี: ความเร็วในการสืบค้นเร็วสุดและโครงสร้างข้อมูลที่สามารถเข้าถึงความซับซ้อนของเวลา O (1) คือ HashMap ข้อมูลการจัดเก็บความยาวตัวแปรแบบไดนามิก (เทียบกับอาร์เรย์)
ข้อเสีย: ค่าแฮชจะต้องคำนวณเพิ่มเติมและหากไม่ได้รับการจัดการอย่างถูกต้องก็จะต้องใช้พื้นที่เพิ่มเติม
- ใช้ HashMap ได้อย่างไร
โดยปกติเราจะใช้ HashMap ดังนี้
แผนที่ <จำนวนเต็ม, สตริง> แผนที่ = ใหม่ hashmap <จำนวนเต็ม, สตริง> (); maps.put (1, "a"); maps.put (2, "b");
รหัสข้างต้นสร้าง HashMap ใหม่และแทรกข้อมูลสองข้อมูล ประเภทข้อมูลพื้นฐานไม่ได้รับการยอมรับที่นี่เพื่อทำ K และ V
หากคุณเขียนสิ่งนี้จะมีปัญหา:
แผนที่ <int, double> maps = new hashmap <int, double> ();
ทำไมเราถึงใช้วิธีนี้? โปรดดูซอร์สโค้ด:
คลาสสาธารณะ hashmap <k, v> ขยาย AbstractMap <k, v> ใช้แผนที่ <k, v>, cloneable, serializable
นี่คือคำจำกัดความของคลาสการใช้งาน HASHMAP
―hashmap เป็นโครงสร้างข้อมูลความยาวตัวแปรแบบไดนามิก-
เมื่อใช้ HASHMAP เพื่อปรับปรุงประสิทธิภาพการดำเนินการเรามักจะตั้งค่าความสามารถในการเริ่มต้น HASHMAP:
แผนที่ <string, string> rm = new hashmap <string, string> (2)
หรือใช้แผนที่คลาสเครื่องมือของ Guava เพื่อสร้างคอลเลกชันและเริ่มต้นค่าด้วยขนาดที่เหมาะสม
แผนที่ <สตริงวัตถุ> map = maps.newhashmapwethexpectedSize (7);
แล้วทำไมต้องใช้แบบนี้? ลองดูที่ตัวสร้างแหล่งที่มาของพวกเขา
ตัวสร้างที่ไม่มีพารามิเตอร์:
public hashmap () {this.loadfactor = default_load_factor; threshold = (int) (default_initial_capacity * default_load_factor); ตาราง = รายการใหม่ [default_initial_capacity]; init (); - Public HashMap () {
this.loadfactor = default_load_factor;
threshold = (int) (default_initial_capacity * default_load_factor);
ตาราง = รายการใหม่ [default_initial_capacity];
init ();
-
/** * สร้าง <tt> HashMap ที่ว่างเปล่า </tt> ด้วยความจุเริ่มต้น * เริ่มต้นที่ระบุและปัจจัยการโหลดเริ่มต้น (0.75) * * @param การเริ่มต้นความจุเริ่มต้น * @THROWS unglemalargumentException หากความสามารถเริ่มต้นเป็นลบ */ public hashmap (int initialcapacity) {this (initialcapacity, default_load_factor); -คำอธิบายของคำนาม:
default_load_factor // ปัจจัยการโหลดเริ่มต้น 0.75 หากไม่ได้ระบุ default_initial_capacity // ความสามารถในการเริ่มต้นเริ่มต้นค่าเริ่มต้นคือ 16 เกณฑ์ // ค่า Threshold (YU) ถูกคำนวณตามปัจจัยการโหลดและความสามารถในการเริ่มต้น <span style = "สี: RGB (54, 46, 43); Font-Family:" Microsoft Yahei ";"> Threshold หมายความว่าเมื่อขนาดของ HashMap มากกว่าเกณฑ์การดำเนินการปรับขนาดจะดำเนินการ
ดังนั้นเราจึงรู้ว่าถ้าเราเรียกตัวสร้างพารามิเตอร์เราจะได้รับอาร์เรย์ของความจุ 16 อาร์เรย์
คำถามคือ: ถ้าความจุเริ่มต้นไม่เพียงพอ?
อาร์เรย์มีความยาวคงที่วิธีการใช้ข้อมูลความยาวคงที่เพื่อแสดงข้อมูลความยาวไม่แน่นอน? คำตอบคือการหาคำตอบที่ยาวขึ้น แต่จะลดประสิทธิภาพเมื่อขนาด ดังนั้นเราขอแนะนำว่า HashMap จะได้รับความสามารถที่เชื่อถือได้เมื่อเริ่มต้น
- วิธีการวาง hashmap -
Public V Put (k key, v value) {ถ้า (key == null) // ถ้าคีย์ว่างเปล่าความแตกต่างระหว่าง HashMap และ Hashtable returns putforNullkey (ค่า); int hash = hash (key.hashcode ()); // เฟรมค่าแฮชตาม hashcode ของคีย์ int i = indexfor (hash, table.length); // เฟรมตัวห้อยอาร์เรย์ที่จะใส่ลงไปตามค่าแฮชสำหรับ (รายการ <k, v> e = ตาราง [i]; e! = null; e = e.next) {// ทั้งหมดสำหรับลูปใช้ถ้า k มีอยู่แล้วแทนที่ v วัตถุ v k; if (e.hash == hash && ((k = e.key) == key || key.equals (k))) {v oldValue = e.value; e.value = ค่า; E.RecordAccess (นี่); กลับ OldValue; }} modcount ++; // ตัวนับตัวเลือก (แฮช, คีย์, ค่า, i); // เพิ่มไปยังอาร์เรย์ส่งคืนค่า null; -หากข้อมูลที่แทรกเกินความจุที่มีอยู่จะถูกดำเนินการ
Addentry (แฮช, คีย์, ค่า, i);
เป็นโมฆะ addentry (int hash, k key, v ค่า V, int bucketindex) {entry <k, v> e = ตาราง [bucketindex]; ตาราง [BucketIndex] = รายการใหม่ <k, v> (แฮช, คีย์, ค่า, e); if (size ++> = threshold) <span style = "สี:#ff0000;"> <strong> ปรับขนาด (2 * table.length);}ที่นี่หากขนาดปัจจุบัน ++> เกณฑ์จะปรากฏขึ้นขนาดปัจจุบันจะถูกขยายสองครั้งและปรับขนาด (2*table.length) จะถูกดำเนินการ แล้วพวกเขาจะขยายได้อย่างไร?
โมฆะปรับขนาด (int newCapacity) {entry [] oldTable = ตาราง; int oldcapacity = oldTable.length; if (oldcapacity == maximum_capacity) {threshold = integer.max_value; กลับ; } รายการ [] newTable = รายการใหม่ [newCapacity]; <span style = "สี: rgb (51, 51, 51); font-family: arial;"> ใหม่อาเรย์ใหม่, </span> <strong> <span style = "สี:#ff0000;"> โอน (newtable); </span> </strong> threshold = (int) (newCapacity * loadfactor); // คำนวณความจุใหม่}การถ่ายโอนการถ่ายโอนการถ่ายโอนการถ่ายโอนอย่างไร?
โมฆะการถ่ายโอน (รายการ [] newTable) {entry [] src = ตาราง; int newCapacity = newTable.length; สำหรับ (int j = 0; j <src.length; j ++) {entry <k, v> e = src [j]; if (e! = null) {src [j] = null; ทำ {entry <k, v> next = e.next; int i = <strong> <span style = "สี:#ff0000;"> indexfor (e.hash, newcapacity); // คำนวณดัชนีใหม่ตามความจุของค่าแฮช </span> </strong> e.next = newTable [i]; newTable [i] = e; e = ถัดไป; } ในขณะที่ (e! = null); -- จำนวนการดำเนินการเพิ่มเติมของการขยาย HashMap-
ดังนั้นหากเราต้องการเพิ่ม HashMap ของ 1,000 องค์ประกอบหากเราใช้ค่าเริ่มต้นฉันต้องคำนวณเพิ่มเติมกี่ครั้งในการคำนวณ
เมื่อมากกว่า 16*0.75 = 12 จะต้องมีการคำนวณใหม่ 12 ครั้ง
เมื่อมากกว่า 16*2*0.75 = 24 จำเป็นต้องมีการคำนวณเพิ่มเติม 24 ครั้ง
-
เมื่อมากกว่า 16*n*0.75 = 768 จำเป็นต้องมีการคำนวณเพิ่มเติม 768
ดังนั้นเราจึงคำนวณ 12+24+48+…+768 เท่าในกระบวนการขยาย
ดังนั้นจึงขอแนะนำอย่างยิ่งว่าเราควรระบุขนาดเริ่มต้นด้วยตนเองหากเรารู้ขอบเขตในโครงการเช่นนี้:
แผนที่ <จำนวนเต็ม, สตริง> แผนที่ = ใหม่ hashmap <จำนวนเต็ม, สตริง> (1,000);
สรุป: นี่คือเหตุผลที่ประสิทธิภาพการดำเนินการของ HashMap ลดลงอย่างรุนแรงหากเกินความจุเริ่มต้นระหว่างการใช้งาน
ข้างต้นคือทั้งหมดที่เกี่ยวกับการใช้ HashMap ในบทความนี้เกี่ยวกับการวิเคราะห์ซอร์สโค้ด Java ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!