ความสำคัญของปัจจัยโหลดใน HashMap คืออะไร?


232

HashMapมีสองคุณสมบัติที่สำคัญและsize load factorฉันอ่านเอกสาร Java แล้วมันบอกว่า0.75fเป็นตัวประกอบการโหลดครั้งแรก แต่ฉันไม่พบการใช้งานจริงของมัน

มีใครบ้างที่สามารถอธิบายสถานการณ์ที่แตกต่างกันซึ่งเราจำเป็นต้องตั้งค่าตัวประกอบภาระและค่าตัวอย่างในอุดมคติสำหรับกรณีที่แตกต่างกันคืออะไร

คำตอบ:


266

เอกสารอธิบายว่ามันสวยดี:

อินสแตนซ์ของ HashMap มีสองพารามิเตอร์ที่มีผลต่อประสิทธิภาพการทำงาน: ความจุเริ่มต้นและตัวประกอบภาระ ความจุคือจำนวนที่เก็บข้อมูลในตารางแฮชและความจุเริ่มต้นเป็นเพียงความจุ ณ เวลาที่สร้างตารางแฮช ตัวประกอบภาระคือการวัดความเต็มของตารางแฮชที่ได้รับก่อนที่ความจุจะเพิ่มขึ้นโดยอัตโนมัติ เมื่อจำนวนรายการในตารางแฮชเกินกว่าผลิตภัณฑ์ของปัจจัยการโหลดและกำลังการผลิตปัจจุบันตารางแฮชจะถูก rehashed (นั่นคือโครงสร้างข้อมูลภายในจะถูกสร้างขึ้นมาใหม่) เพื่อให้ตารางแฮชมีจำนวนถังประมาณสองเท่า

ตามกฎทั่วไปค่าตัวโหลดเริ่มต้น (.75) ให้การแลกเปลี่ยนที่ดีระหว่างเวลาและค่าใช้จ่ายของพื้นที่ ค่าที่สูงกว่าจะลดค่าใช้จ่ายของพื้นที่ แต่เพิ่มค่าการค้นหา (สะท้อนในการดำเนินการส่วนใหญ่ของคลาส HashMap รวมถึงการรับและวาง) จำนวนที่คาดหวังของรายการในแผนที่และปัจจัยการโหลดควรนำมาพิจารณาเมื่อตั้งค่าความจุเริ่มต้นเพื่อลดจำนวนของการดำเนินการปรับปรุงใหม่ หากความจุเริ่มต้นมากกว่าจำนวนสูงสุดของรายการหารด้วยปัจจัยโหลดจะไม่มีการดำเนินการปรับปรุงใหม่

เช่นเดียวกับการเพิ่มประสิทธิภาพทั้งหมดมันเป็นความคิดที่ดีที่จะหลีกเลี่ยงการปรับให้เหมาะสมก่อนเวลาอันควร (เช่นไม่มีข้อมูลที่ยากว่าคอขวดอยู่ที่ไหน)


14
คำตอบอื่น ๆ จะบอกระบุcapacity = N/0.75เพื่อหลีกเลี่ยงการ rehashing load factor = 1แต่คิดเริ่มต้นของฉันได้เพียงแค่ตั้ง จะมีข้อเสียสำหรับวิธีการนั้นหรือไม่? ทำไมปัจจัยโหลดจะส่งผลกระทบget()และput()ค่าใช้จ่ายในการดำเนินงาน?
supermitch

19
โหลดปัจจัย = 1 hashmap ที่มีจำนวนรายการ = ความจุจะมีการชนกันทางสถิติอย่างมีนัยสำคัญ (= เมื่อหลายคีย์กำลังผลิตแฮชเดียวกัน) เมื่อการชนเกิดขึ้นเวลาค้นหาจะเพิ่มขึ้นเช่นเดียวกับที่ฝากข้อมูลหนึ่งรายการ> 1 รายการที่ตรงกันซึ่งต้องตรวจสอบคีย์แต่ละรายการเพื่อความเท่าเทียมกัน คณิตศาสตร์ที่มีรายละเอียดบางอย่าง: preshing.com/20110504/hash-collision-probabilities
atimb

8
ฉันไม่ได้ติดตามคุณ @atimb; คุณสมบัติ loadset ใช้เพื่อกำหนดว่าจะเพิ่มขนาดพื้นที่จัดเก็บเมื่อใด - วิธีที่จะมีหนึ่งชุดเพิ่มหนึ่งโอกาสในการชนกันของแฮช? - อัลกอริทึมการแปลงแป้นพิมพ์ไม่มีความรู้เกี่ยวกับจำนวนรายการที่อยู่ในแผนที่หรือความถี่ที่จะได้รับ "ถัง" หน่วยเก็บข้อมูลใหม่ ฯลฯ สำหรับชุดของวัตถุใด ๆ ที่มีขนาดเท่ากันไม่ว่าคุณจะถูกเก็บไว้อย่างไร ความน่าจะเป็นแบบเดียวกันกับค่าแฮชซ้ำ ...
BrainSlugs83

19
ความน่าจะเป็นของการชนกันของแฮชจะน้อยลงหากขนาดของแผนที่ใหญ่ขึ้น ตัวอย่างเช่นองค์ประกอบที่มีรหัสแฮช 4, 8, 16 และ 32 จะถูกวางลงในที่ฝากข้อมูลเดียวกันหากขนาดของแผนที่คือ 4 แต่ทุกรายการจะได้รับที่เก็บข้อมูลของตนเองถ้าขนาดของแผนที่มากกว่า 32 แผนที่ที่มีขนาดเริ่มต้น 4 และตัวประกอบภาระ 1.0 (4 ถัง แต่องค์ประกอบ 4 ทั้งหมดในที่เก็บข้อมูลเดียว) จะอยู่ในตัวอย่างนี้โดยเฉลี่ยสองครั้งช้ากว่าอีกอันหนึ่งที่มีตัวประกอบภาระ 0.75 (8 ถังสองถังเต็ม - ด้วยองค์ประกอบ "4" และด้วยองค์ประกอบ "8", "16", "32")
30th

1
@Adelin Lookup ต้นทุนเพิ่มขึ้นสำหรับปัจจัยโหลดที่สูงขึ้นเนื่องจากจะมีการชนกันมากขึ้นสำหรับค่าที่สูงขึ้นและวิธีที่ Java จัดการการชนคือการวางรายการที่มีแฮชโค้ดเดียวกันในที่ฝากข้อมูลเดียวกันโดยใช้โครงสร้างข้อมูล เริ่มต้นใน Java 8 โครงสร้างข้อมูลนี้เป็นแผนผังการค้นหาแบบไบนารี สิ่งนี้ทำให้การค้นหาเวลาที่เลวร้ายที่สุดกรณีที่ซับซ้อน O (lg (n)) กับกรณีที่เลวร้ายที่สุดที่เกิดขึ้นหากองค์ประกอบทั้งหมดที่เพิ่มเข้ามามีรหัสแฮชเดียวกัน
Gigi Bayte 2

141

ความจุเริ่มต้นเริ่มต้นของการถ่ายHashMapคือ 16 และตัวประกอบภาระคือ 0.75f ​​(เช่น 75% ของขนาดแผนที่ปัจจุบัน) ตัวประกอบภาระแสดงระดับHashMapความจุที่ควรเพิ่มเป็นสองเท่า

ตัวอย่าง16 * 0.75 = 12สินค้าของความจุและโหลดปัจจัยที่เป็น นี่แสดงว่าหลังจากจัดเก็บคู่คีย์ - ค่าที่ 12 ลงในHashMapความจุของมันจะกลายเป็น 32


3
แม้ว่าคำตอบของคุณจะชัดเจน แต่คุณสามารถบอกได้ไหมว่าหลังจากที่เก็บคู่คีย์ - ค่า 12 คู่ความจุจะกลายเป็น 32 หรือว่าเมื่อเพิ่มรายการที่ 13 ในเวลานั้นความจุเปลี่ยนไปแล้วจึงใส่รายการ
userab

หมายความว่าจำนวนถังเพิ่มขึ้น 2 หรือไม่
LoveMeow

39

ที่จริงจากการคำนวณของฉันปัจจัยโหลด "สมบูรณ์แบบ" นั้นอยู่ใกล้กับบันทึก 2 (~ 0.7) แม้ว่าปัจจัยโหลดใด ๆ ที่น้อยกว่านี้จะให้ประสิทธิภาพที่ดีขึ้น ฉันคิดว่า. 75 อาจถูกดึงออกมาจากหมวก

พิสูจน์:

สามารถหลีกเลี่ยงการผูกมัดและทำนายการใช้ประโยชน์จากสาขาโดยทำนายว่าที่ฝากข้อมูลว่างเปล่าหรือไม่ ที่ฝากข้อมูลอาจว่างเปล่าถ้าความน่าจะเป็นที่ว่างเปล่าเกินกว่า 0.5

ให้ s แทนขนาดและจำนวนของปุ่มที่เพิ่มเข้าไป ใช้ทฤษฎีบททวินามความน่าจะเป็นที่ฝากข้อมูลว่างเปล่าคือ:

P(0) = C(n, 0) * (1/s)^0 * (1 - 1/s)^(n - 0)

ดังนั้นถังอาจว่างเปล่าหากมีน้อยกว่า

log(2)/log(s/(s - 1)) keys

เมื่อถึงจำนวนอนันต์และหากจำนวนของคีย์ที่เพิ่มเป็นเช่นนั้น P (0) = .5 ดังนั้น n / s จะเข้าสู่ระบบ (2) อย่างรวดเร็ว:

lim (log(2)/log(s/(s - 1)))/s as s -> infinity = log(2) ~ 0.693...

4
คณิตศาสตร์ผู้เรียน FTW! มีแนวโน้มที่จะ.75ถูกปัดเศษเป็นเศษส่วนที่ใกล้ที่สุดซึ่งง่ายต่อการเข้าใจlog(2)และดูเหมือนว่าจะมีจำนวนน้อยกว่าเวทย์มนตร์ ฉันชอบที่จะเห็นการปรับปรุงค่าเริ่มต้นของ JDK พร้อมความคิดเห็นดังกล่าวข้างต้นการใช้งาน: D
ถอดรหัส

2
ฉันต้องการคำตอบนี้จริง ๆ แต่ฉันเป็นนักพัฒนา JavaEE ซึ่งหมายความว่าคณิตศาสตร์ไม่เหมาะกับฉันจริงๆดังนั้นฉันจึงเข้าใจน้อยมากในสิ่งที่คุณเขียน lol
searchengine27

28

ตัวประกอบภาระคืออะไร?

ปริมาณของความจุที่ต้องใช้หมดสำหรับ HashMap เพื่อเพิ่มกำลังการผลิต?

ทำไมถึงเป็นปัจจัยโหลด

ตัวประกอบภาระโดยค่าเริ่มต้น 0.75 ของความจุเริ่มต้น (16) ดังนั้น 25% ของที่เก็บข้อมูลจะว่างก่อนที่จะมีการเพิ่มความจุ & สิ่งนี้ทำให้ที่เก็บข้อมูลใหม่พร้อมกับ hashcodes ใหม่ชี้ไปที่พวกเขาอยู่หลังจากการเพิ่มขึ้น จำนวนถัง

ตอนนี้ทำไมคุณควรเก็บถังฟรีมากมายและผลกระทบของการรักษาถังฟรีต่อประสิทธิภาพคืออะไร

หากคุณตั้งค่าตัวประกอบกำลังโหลดเป็น 1.0 นั่นอาจเป็นสิ่งที่น่าสนใจมาก

สมมติว่าคุณกำลังเพิ่มวัตถุ x ใน hashmap ของคุณซึ่ง hashCode คือ 888 และใน hashmap ของคุณ bucket ที่เป็นตัวแทนของ hashcode นั้นฟรีดังนั้นobject xจะถูกเพิ่มในที่เก็บข้อมูล แต่ตอนนี้พูดอีกครั้งว่าถ้าคุณเพิ่มวัตถุ y อีกอันที่ hashCode ยัง 888 แล้ววัตถุของคุณจะได้รับการเพิ่มแน่นอน แต่ในตอนท้ายของถัง ( เพราะถังไม่มีอะไรเลยนอกจากการดำเนินการเชื่อมโยงรายการการจัดเก็บคีย์ค่า & ถัดไป ) ตอนนี้มีผลกระทบต่อประสิทธิภาพ! เนื่องจากอ็อบเจกต์ yของคุณไม่อยู่ในหัวถังอีกต่อไปหากคุณทำการค้นหาเวลาที่ใช้จะไม่เป็นO (1)เวลานี้มันขึ้นอยู่กับจำนวนรายการที่มีในที่เก็บข้อมูลเดียวกัน สิ่งนี้เรียกว่า hash collision โดยวิธีนี้เกิดขึ้นเมื่อปัจจัยการโหลดของคุณน้อยกว่า 1

ความสัมพันธ์ระหว่างประสิทธิภาพการชนกันของข้อมูลการแฮช & ตัวประกอบการโหลด?

ปัจจัยโหลดต่ำ = ถังฟรีมากขึ้น = โอกาสในการชนน้อยลง = ประสิทธิภาพสูง = ความต้องการพื้นที่สูง

แก้ไขฉันหากฉันผิดที่ไหนสักแห่ง


2
คุณสามารถเพิ่มบิตเกี่ยวกับวิธีที่ hashCode ถูกถอดออกเป็นตัวเลขด้วยช่วง 1- {count bucket} และดังนั้นจึงไม่ใช่จำนวนถังที่ต่อ แต่ท้ายผลลัพธ์ของอัลกอริทึมแฮชจะครอบคลุม ช่วงที่ใหญ่ขึ้น HashCode ไม่ใช่แฮชอัลกอริธึมแบบเต็มมันมีขนาดเล็กพอที่จะประมวลผลได้ง่าย ดังนั้นจึงไม่มีแนวคิดของ "ถังฟรี" แต่ "จำนวนถังฟรีขั้นต่ำ" เนื่องจากคุณสามารถจัดเก็บองค์ประกอบทั้งหมดของคุณไว้ในที่เก็บเดียวกัน แต่เป็นพื้นที่สำคัญของแฮชโค้ดของคุณซึ่งเท่ากับความจุ * (1 / load_factor) 40 องค์ประกอบ, 0.25 ตัวประกอบโหลด = 160 ถัง
user1122069

ฉันคิดว่าเวลาค้นหาสำหรับวัตถุจากLinkedListถูกเรียกว่าAmortized Constant Execution Timeและแสดง+เป็นO(1)+
Raf

19

จากเอกสาร :

ตัวประกอบภาระคือการวัดความเต็มของตารางแฮชที่ได้รับก่อนที่ความจุจะเพิ่มขึ้นโดยอัตโนมัติ

มันขึ้นอยู่กับข้อกำหนดเฉพาะของคุณไม่มี "กฎง่ายๆ" สำหรับระบุตัวประกอบการโหลดเริ่มต้น


เอกสารยังระบุด้วยว่า "ตามกฎทั่วไปตัวประกอบการโหลดเริ่มต้น (.75) มอบการแลกเปลี่ยนที่ดีระหว่างต้นทุนเวลาและพื้นที่" ดังนั้นสำหรับผู้ที่ไม่แน่ใจค่าเริ่มต้นคือกฎง่ายๆ
ferekdoley

4

สำหรับ HashMap DEFAULT_INITIAL_CAPACITY = 16และDEFAULT_LOAD_FACTOR = 0.75f ก็หมายความว่าจำนวน MAX ทุกรายการใน HashMap = 16 * 0.75 = 12 เมื่อองค์ประกอบที่สิบสามจะถูกเพิ่มความจุ (ขนาดอาร์เรย์) ของ HashMap จะเป็นสองเท่า! ภาพประกอบที่สมบูรณ์แบบตอบคำถามนี้: นำ ป้อนคำอธิบายรูปภาพที่นี่ ภาพมาจากที่นี่:

https://javabypatel.blogspot.com/2015/10/what-is-load-factor-and-rehashing-in-hashmap.html


2

ถ้าถังเต็มเกินไปเราต้องมองผ่าน

รายการเชื่อมโยงที่ยาวมาก

และนั่นคือการเอาชนะประเด็น

นี่คือตัวอย่างที่ฉันมีสี่ถัง

ฉันมีช้างและแบดเจอร์ในแฮชเซ็ตของฉันจนถึงตอนนี้

นี่เป็นสถานการณ์ที่ดีทีเดียว

แต่ละองค์ประกอบมีศูนย์หรือหนึ่งองค์ประกอบ

ตอนนี้เราได้เพิ่มองค์ประกอบสองอย่างเข้าไปใน HashSet ของเรา

     buckets      elements
      -------      -------
        0          elephant
        1          otter
         2          badger
         3           cat

นี่มันก็ไม่ได้แย่เหมือนกัน

ถังทุกอันมีองค์ประกอบเดียวเท่านั้น ถ้าฉันอยากรู้มันมีแพนด้าอยู่ไหม?

ฉันสามารถดูหมายเลขถัง 1 อย่างรวดเร็วและไม่ใช่

ที่นั่นและ

ฉันรู้ว่ามันไม่ได้อยู่ในคอลเลกชันของเรา

ถ้าฉันอยากรู้ว่ามันมีแมวอยู่หรือเปล่า

หมายเลข 3

ฉันพบแมวฉันรู้ว่ามันอยู่ในนั้นหรือไม่

ชุด

ถ้าฉันเพิ่มโคอาล่าแล้วล่ะก็มันก็ไม่เลว

             buckets      elements
      -------      -------
        0          elephant
        1          otter -> koala 
         2          badger
         3           cat

อาจจะตอนนี้แทนที่จะเป็นที่ฝากข้อมูลหมายเลข 1 เท่านั้นที่ดู

องค์ประกอบหนึ่ง

ฉันต้องดูสองคน

แต่อย่างน้อยฉันก็ไม่จำเป็นต้องดูช้างตัวแบดเจอร์และ

แมว.

ถ้าฉันกำลังมองหาหมีแพนด้าอีกครั้งมันจะอยู่ในถังเท่านั้น

หมายเลข 1 และ

ฉันไม่ต้องมองอะไรเลยนอกจากนากแล้ว

สัตว์มีถุงหน้าท้องคล้ายหมี

แต่ตอนนี้ฉันใส่จระเข้ในถังหมายเลข 1 แล้วคุณก็ทำได้

ดูบางทีสิ่งนี้กำลังจะไป

นั่นคือถ้าถังหมายเลข 1 ใหญ่ขึ้นเรื่อย ๆ และ

ที่ใหญ่กว่านั้นฉันต้องมองผ่านทั้งหมด

องค์ประกอบเหล่านั้นเพื่อค้นหา

สิ่งที่ควรอยู่ใน bucket จำนวน 1

            buckets      elements
      -------      -------
        0          elephant
        1          otter -> koala ->alligator
         2          badger
         3           cat

ถ้าฉันเริ่มเพิ่มสตริงลงในที่เก็บข้อมูลอื่น

ถูกต้องปัญหาใหญ่ขึ้นเรื่อย ๆ ในทุก ๆ

ถังเดียว

เราจะหยุดถังของเราให้เต็มได้อย่างไร?

ทางออกที่นี่ก็คือ

          "the HashSet can automatically

        resize the number of buckets."

มี HashSet ตระหนักว่าถังกำลังได้รับ

เต็มเกินไป

มันสูญเสียความได้เปรียบจากการค้นหานี้ทั้งหมด

องค์ประกอบ

และมันจะสร้างถังมากขึ้น (โดยทั่วไปเป็นสองเท่าก่อนหน้านี้) และ

จากนั้นวางองค์ประกอบลงในที่ฝากข้อมูลที่ถูกต้อง

ดังนั้นนี่คือการติดตั้ง HashSet พื้นฐานของเราด้วยการแยก

การผูกมัด ตอนนี้ฉันกำลังจะสร้าง "HashSet ที่ปรับขนาดตัวเอง"

HashSet นี้จะรู้ว่าถังบรรจุนั้น

รับเต็มเกินไปและ

มันต้องการถังเพิ่ม

loadFactor เป็นอีกฟิลด์หนึ่งในคลาส HashSet ของเรา

loadFactor แสดงถึงจำนวนเฉลี่ยขององค์ประกอบต่อ

ถัง,

ด้านบนซึ่งเราต้องการปรับขนาด

loadFactor คือความสมดุลระหว่างพื้นที่และเวลา

หากถังเต็มเกินไปเราจะปรับขนาด

แน่นอนว่าต้องใช้เวลา แต่

มันอาจช่วยเราประหยัดเวลาในการเดินทางหากถังเก็บน้ำเป็น

ที่ว่างเปล่าน้อยมาก

ลองดูตัวอย่าง

นี่คือ HashSet เราได้เพิ่มองค์ประกอบสี่อย่างแล้ว

ช้าง, สุนัข, แมวและปลา

          buckets      elements
      -------      -------
        0          
        1          elephant
         2          cat ->dog
         3           fish
          4         
           5

ณ จุดนี้ฉันได้ตัดสินใจแล้วว่า loadFactor, the

เกณฑ์

จำนวนเฉลี่ยขององค์ประกอบต่อถังที่ฉันโอเค

ด้วยคือ 0.75

จำนวนของถังคือที่เก็บข้อมูลความยาวซึ่งคือ 6 และ

ณ จุดนี้ HashSet ของเรามีองค์ประกอบสี่อย่างดังนั้น

ขนาดปัจจุบันคือ 4

เราจะปรับขนาด HashSet ของเรานั่นคือเราจะเพิ่มที่เก็บข้อมูลเพิ่มเติม

เมื่อจำนวนเฉลี่ยขององค์ประกอบต่อถังมากกว่า

loadFactor

นั่นคือเมื่อขนาดปัจจุบันหารด้วยที่เก็บข้อมูลความยาวคือ

มากกว่า loadFactor

ณ จุดนี้จำนวนเฉลี่ยขององค์ประกอบต่อถัง

คือ 4 หารด้วย 6

4 องค์ประกอบ 6 ถังนั่นคือ 0.67

นั่นน้อยกว่าขีด จำกัด ที่ฉันตั้งไว้ที่ 0.75 เราก็เลย

ตกลง.

เราไม่จำเป็นต้องปรับขนาด

แต่ตอนนี้สมมติว่าเราเพิ่ม woodchuck

                  buckets      elements
      -------      -------
        0          
        1          elephant
         2        woodchuck-> cat ->dog
         3           fish
          4         
           5

Woodchuck จะจบลงด้วยหมายเลขถัง 3

ณ จุดนี้ขนาดปัจจุบันคือ 5

และตอนนี้จำนวนเฉลี่ยขององค์ประกอบต่อถัง

คือขนาดปัจจุบันหารด้วยที่เก็บข้อมูลความยาว

นั่นคือ 5 องค์ประกอบหารด้วย 6 ถังคือ 0.83

และสิ่งนี้สูงกว่า loadFactor ซึ่งเท่ากับ 0.75

เพื่อที่จะแก้ไขปัญหานี้เพื่อที่จะทำให้

ถังอาจจะเล็กน้อย

ว่างมากขึ้นเพื่อให้การดำเนินงานเช่นการพิจารณาว่า

ถังบรรจุ

องค์ประกอบจะซับซ้อนน้อยกว่าเล็กน้อยฉันต้องการปรับขนาด

HashSet ของฉัน

การปรับขนาด HashSet มีสองขั้นตอน

ก่อนอื่นฉันจะเพิ่มจำนวนถังเป็นสองเท่าฉันมี 6 ถัง

ตอนนี้ฉันจะมี 12 ถัง

โปรดทราบที่นี่ว่า loadFactor ที่ฉันตั้งไว้ที่ 0.75 ยังคงเหมือนเดิม

แต่จำนวนถังเปลี่ยนเป็น 12

จำนวนองค์ประกอบยังคงเหมือนเดิมคือ 5

5 หารด้วย 12 มีค่าประมาณ 0.42 ซึ่งอยู่ภายใต้เรา

loadFactor,

ดังนั้นเราโอเคตอนนี้

แต่เราไม่ได้ทำเพราะองค์ประกอบเหล่านี้บางอย่างอยู่

ตอนนี้ผิดถัง

ตัวอย่างเช่นช้าง

ช้างอยู่ในถังหมายเลข 2 เพราะจำนวน

ตัวละครในช้าง

เท่ากับ 8

เรามี 6 ฝาก 8 ลบ 6 คือ 2

นั่นเป็นเหตุผลที่มันลงเอยในหมายเลข 2

แต่ตอนนี้เรามีถัง 12 ถัง 8 mod 12 คือ 8 ดังนั้น

ช้างไม่ได้อยู่ในถังหมายเลข 2 อีกต่อไป

ช้างอยู่ในถังหมายเลข 8

สิ่งที่เกี่ยวกับ woodchuck

Woodchuck เป็นคนที่เริ่มต้นปัญหาทั้งหมดนี้

Woodchuck จบลงด้วยหมายเลขถัง 3

เพราะ 9 mod 6 คือ 3

แต่ตอนนี้เราทำ 9 mod 12

9 mod 12 คือ 9, woodchuck ไปที่ bucket จำนวน 9

และคุณเห็นข้อได้เปรียบทั้งหมดนี้

ตอนนี้หมายเลขถัง 3 เท่านั้นมีสององค์ประกอบในขณะที่ก่อนมี 3

นี่คือรหัสของเรา

ที่เรามี HashSet ของเราด้วยการผูกมัดที่แยกต่างหาก

ไม่ได้ทำการปรับขนาด

ตอนนี้นี่คือการใช้งานใหม่ที่เราใช้การปรับขนาด

รหัสนี้ส่วนใหญ่เหมือนกัน

เราจะยังคงตรวจสอบว่ามันมี

คุ้มค่าแล้ว

หากไม่เป็นเช่นนั้นเราจะหาว่าถังใด

ควรเข้าไปและ

จากนั้นเพิ่มลงในที่ฝากข้อมูลนั้นเพิ่มไปยัง LinkedList นั้น

แต่ตอนนี้เราเพิ่มฟิลด์ขนาดปัจจุบัน

currentSize คือฟิลด์ที่ติดตามจำนวน

ขององค์ประกอบใน HashSet ของเรา

เรากำลังจะเพิ่มมันแล้วเราจะไปดู

ที่ภาระเฉลี่ย

จำนวนเฉลี่ยขององค์ประกอบต่อถัง

เราจะทำส่วนนั้นลงที่นี่

เราต้องทำการคัดเลือกนักแสดงที่นี่เพื่อให้แน่ใจ

ที่เราได้รับสองเท่า

จากนั้นเราจะเปรียบเทียบโหลดเฉลี่ยกับฟิลด์

ที่ฉันตั้งไว้

0.75 เมื่อฉันสร้าง HashSet นี้ซึ่งก็คือ

loadFactor

หากโหลดเฉลี่ยมากกว่า loadFactor

นั่นหมายความว่ามีองค์ประกอบต่อถังมากเกินไป

โดยเฉลี่ยและฉันต้องการแทรกอีกครั้ง

ดังนั้นนี่คือการดำเนินการตามวิธีการของเราเพื่อแทรกเข้าไปใหม่

องค์ประกอบทั้งหมด

ก่อนอื่นฉันจะสร้างตัวแปรท้องถิ่นชื่อว่า oldBuckets

ซึ่งหมายถึงถังที่พวกเขายืนอยู่ในขณะนี้

ก่อนที่ฉันจะเริ่มปรับขนาดทุกอย่าง

หมายเหตุฉันยังไม่ได้สร้างรายการลิงก์ที่เรียงลำดับใหม่

ฉันแค่เปลี่ยนชื่อถังเป็นถังขยะเก่า

ตอนนี้จำได้ว่าถังเป็นทุ่งในชั้นเรียนของเราฉันจะไป

เพื่อสร้างอาร์เรย์ใหม่

ของรายการที่ลิงก์ แต่สิ่งนี้จะมีองค์ประกอบสองเท่า

เหมือนครั้งแรกที่ทำ

ตอนนี้ฉันต้องทำการ reinserting จริง ๆ

ฉันจะทำซ้ำผ่านถังเก่าทั้งหมด

แต่ละองค์ประกอบใน oldBuckets เป็น LinkedList ของสตริง

นั่นคือถัง

ฉันจะผ่านที่ฝากข้อมูลนั้นและรับองค์ประกอบแต่ละอย่างในนั้น

ถัง.

และตอนนี้ฉันจะใส่เข้าไปใน Buckets ใหม่

ฉันจะรับ hashCode ของมัน

ฉันจะหาว่าเป็นดัชนีใด

และตอนนี้ฉันได้ถังใหม่แล้ว LinkedList ใหม่ของ

สตริงและ

ฉันจะเพิ่มลงในถังใหม่

ดังนั้นในการสรุป HashSets อย่างที่เราเห็นคือ Array of Linked

รายการหรือถัง

HashSet ที่ปรับขนาดตัวเองสามารถตระหนักถึงการใช้อัตราส่วนหรือ


1

ฉันจะเลือกขนาดตารางที่ n * 1.5 หรือ n + (n >> 1) นี่จะให้โหลดแฟคเตอร์เป็น. 66666 ~ โดยไม่มีการหารซึ่งช้าในระบบส่วนใหญ่โดยเฉพาะอย่างยิ่งในระบบพกพาที่ไม่มีการแบ่งใน ฮาร์ดแวร์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.