วิธี Equals และวิธีการ HashCode ใน Java อยู่ในวัตถุดังนั้นแต่ละวัตถุมีสองวิธีนี้ บางครั้งเราจำเป็นต้องใช้ความต้องการเฉพาะและอาจต้องเขียนสองวิธีนี้ใหม่ วันนี้เราจะแนะนำฟังก์ชั่นของทั้งสองวิธีนี้
วิธี Equals () และ HashCode () ใช้เพื่อเปรียบเทียบในคลาสเดียวกันโดยเฉพาะอย่างยิ่งเมื่อจัดเก็บวัตถุคลาสเดียวกันในคอนเทนเนอร์เช่น SET เพื่อตรวจสอบว่าวัตถุที่วางไว้นั้นซ้ำกันหรือไม่
ก่อนอื่นเราต้องเข้าใจปัญหา:
วัตถุสองชิ้นที่มีเท่ากับ () เท่ากับ HashCode () จะต้องเท่ากันและวัตถุสองชิ้นที่มีค่าเท่ากับ () ไม่เท่ากันไม่สามารถพิสูจน์ได้ว่า hashCode () ของพวกเขาไม่เท่ากัน กล่าวอีกนัยหนึ่งสำหรับสองวัตถุที่มีค่าเท่ากับ () ไม่เท่ากัน HashCode () อาจเท่ากัน (ความเข้าใจของฉันเกิดจากความขัดแย้งของรหัสแฮชเมื่อสร้างขึ้น)
HashCode ที่นี่เป็นเหมือนดัชนีของตัวละครแต่ละตัวในพจนานุกรมและ Equals () เป็นเหมือนการเปรียบเทียบคำที่แตกต่างกันภายใต้อักขระเดียวกันในพจนานุกรม เช่นเดียวกับในพจนานุกรมค้นหาคำสองคำว่า "ตัวเอง" และ "ธรรมชาติ" ภายใต้คำว่า "ตัวเอง" ในพจนานุกรมถ้า Equals () ถูกใช้เพื่อกำหนดความเท่าเทียมกันของคำสืบค้นคำมันเป็นคำเดียวกัน ตัวอย่างเช่นคำสองคำที่เปรียบเทียบโดย Equals () เป็น "ตัวเอง" จากนั้นค่าที่ได้รับโดยวิธีการ HashCode () จะต้องเท่ากันในเวลานี้; ถ้าเมธอดเท่ากับ () เปรียบเทียบคำว่า "ตัวเอง" และ "ตามธรรมชาติ" ผลลัพธ์ก็คือคุณไม่ต้องการรอ แต่คำทั้งสองนี้เป็นคำว่า "ตัวเอง" และเมื่อค้นหาดัชนีนั่นคือ hashcode () เหมือนกัน ถ้าเท่ากับ () เปรียบเทียบคำว่า "ตนเอง" และ "พวกเขา" ผลลัพธ์ก็แตกต่างกันและผลลัพธ์ที่ได้จาก HashCode () ก็แตกต่างกันในเวลานี้
ในทางกลับกัน: HashCode () นั้นแตกต่างกันและสามารถแนะนำได้ (Equals (); HashCode () เท่ากับเท่ากับ () อาจเท่ากันหรืออาจไม่เท่ากัน ในคลาสวัตถุวิธี HashCode () เป็นวิธีการในท้องถิ่นซึ่งส่งคืนค่าที่อยู่ของวัตถุ เมธอด Equals () ในคลาสวัตถุยังเปรียบเทียบค่าที่อยู่ของวัตถุทั้งสอง ถ้า Equals () เท่ากันก็หมายความว่าค่าที่อยู่ของวัตถุทั้งสองนั้นเท่ากันแน่นอนว่า HashCode () จะเท่ากัน
ในเวลาเดียวกันอัลกอริทึมแฮชให้ประสิทธิภาพสูงสำหรับการค้นหาองค์ประกอบ
หากคุณต้องการทราบว่าวัตถุมีอยู่ในคอลเลกชันคุณจะเขียนรหัสโปรแกรมโดยประมาณได้อย่างไร
คุณมักจะนำองค์ประกอบแต่ละอย่างทีละหนึ่งเพื่อเปรียบเทียบกับวัตถุที่คุณกำลังมองหา เมื่อคุณพบว่าผลลัพธ์ของการเปรียบเทียบวิธี Equals ระหว่างองค์ประกอบและวัตถุที่คุณกำลังมองหาหยุดการค้นหาและส่งคืนข้อมูลเชิงบวก มิฉะนั้นให้ส่งคืนข้อมูลเชิงลบ หากมีองค์ประกอบหลายอย่างในคอลเลกชันเช่น 10,000 องค์ประกอบและไม่มีวัตถุที่คุณกำลังมองหานั่นหมายความว่าโปรแกรมของคุณจะต้องนำองค์ประกอบ 10,000 รายการออกจากคอลเลกชันและเปรียบเทียบทีละรายการเพื่อให้ได้ข้อสรุป
มีคนคิดค้นอัลกอริทึมแฮชเพื่อปรับปรุงประสิทธิภาพของการค้นหาองค์ประกอบจากชุด ด้วยวิธีนี้ชุดจะแบ่งออกเป็นพื้นที่เก็บข้อมูลหลายแห่ง แต่ละวัตถุสามารถคำนวณรหัสแฮชและสามารถจัดกลุ่มรหัสแฮชได้ (คำนวณโดยใช้ฟังก์ชั่นแฮชที่แตกต่างกัน) แต่ละกลุ่มสอดคล้องกับพื้นที่เก็บข้อมูลที่แน่นอน ตามแฮชของวัตถุมันสามารถกำหนดพื้นที่ที่วัตถุควรเก็บไว้ใน. Hashset ใช้อัลกอริทึมแฮชเพื่อเข้าถึงชุดวัตถุ มันใช้วิธีการที่เหลือส่วนที่เหลือของจำนวน n (ฟังก์ชั่นแฮชนี้ง่ายที่สุด) ในการจัดกลุ่มและแบ่งรหัสแฮช คลาส Object กำหนดวิธี HashCode () เพื่อส่งคืนรหัสแฮชของวัตถุ Java แต่ละรายการ เมื่อมองหาวัตถุจากคอลเลกชัน HashSet ระบบ Java จะเรียกวิธี HashCode () ของวัตถุเป็นครั้งแรกเพื่อรับตารางรหัสแฮชของวัตถุ จากนั้นค้นหาพื้นที่จัดเก็บที่สอดคล้องกันตามการแฮชและในที่สุดก็รับแต่ละองค์ประกอบในพื้นที่จัดเก็บและเปรียบเทียบกับวัตถุสำหรับวิธีการเท่ากับ ด้วยวิธีนี้คุณสามารถได้ข้อสรุปโดยไม่ต้องสำรวจองค์ประกอบทั้งหมดในคอลเลกชัน จะเห็นได้ว่าคอลเลกชัน HashSet มีประสิทธิภาพการดึงวัตถุที่ดี แต่ประสิทธิภาพของการจัดเก็บวัตถุในคอลเลกชัน HashSet ค่อนข้างต่ำเนื่องจากเมื่อเพิ่มวัตถุในคอลเลกชัน HashSet คุณต้องคำนวณรหัสแฮชของวัตถุก่อนและกำหนดตำแหน่งที่เก็บของวัตถุในคอลเลกชันตามรหัสแฮชนี้ เพื่อให้แน่ใจว่าวัตถุอินสแตนซ์ของคลาสสามารถเก็บไว้ได้ตามปกติใน HashSet ผลลัพธ์ของวัตถุอินสแตนซ์สองรายการของคลาสนี้จะต้องเท่ากันเมื่อผลลัพธ์เปรียบเทียบโดยวิธี Equals () เท่ากับ; นั่นคือถ้าผลลัพธ์ของ obj1.equals (OBJ2) เป็นจริงดังนั้นผลลัพธ์ของนิพจน์ต่อไปนี้จะต้องเป็นจริงเช่นกัน:
obj1.hashcode () == obj2.hashcode ()
กล่าวอีกนัยหนึ่ง: เมื่อเราเขียนวิธีการเท่ากับวัตถุเราต้องเขียนวิธี HashCode ใหม่ อย่างไรก็ตามหากเราไม่ได้เขียนวิธี HashCode ใหม่วิธี HashCode ในวัตถุวัตถุจะส่งคืนที่อยู่แฮชของวัตถุเสมอและที่อยู่นี้จะไม่เท่ากัน ดังนั้นแม้ว่าวิธีการที่ Equals จะถูกเขียนใหม่ในเวลานี้จะไม่มีผลเฉพาะเพราะหากวิธีการ HashCode ไม่ต้องการรอมันจะไม่เรียกวิธีการเปรียบเทียบสำหรับการเปรียบเทียบดังนั้นจึงไม่มีความหมาย
หากวิธีการ HashCode () ของคลาสไม่เป็นไปตามข้อกำหนดข้างต้นดังนั้นเมื่อผลลัพธ์ของการเปรียบเทียบระหว่างวัตถุอินสแตนซ์ทั้งสองของคลาสนี้จะเท่ากับวิธี Equals () พวกเขาไม่ควรเก็บไว้ในชุดที่ตั้งไว้ในเวลาเดียวกัน อย่างไรก็ตามหากพวกเขาถูกเก็บไว้ในชุด HashSet เนื่องจากค่าคืนสินค้าของวิธีการ HashCode () ของพวกเขานั้นแตกต่างกัน (ค่าส่งคืนของวิธี HashCode ในวัตถุนั้นแตกต่างกันเสมอ) วัตถุที่สองอาจถูกใส่เข้าไปในพื้นที่ที่แตกต่างจากวัตถุแรกตามการคำนวณรหัสแฮช วิธีการ HashCode () ในคลาสวัตถุไม่สามารถปฏิบัติตามข้อกำหนดของวัตถุที่ถูกเก็บไว้ใน HashSet ได้เนื่องจากค่าส่งคืนจะถูกคำนวณจากที่อยู่หน่วยความจำของวัตถุ ค่าแฮชที่ส่งคืนโดยวัตถุเดียวกันเมื่อใดก็ได้ในระหว่างการรันโปรแกรมจะไม่เปลี่ยนแปลงเสมอ ดังนั้นตราบใดที่มันเป็นวัตถุอินสแตนซ์ที่แตกต่างกันสองรายการแม้ว่าผลการเปรียบเทียบของวิธีการเท่ากับของพวกเขาจะเท่ากันค่าส่งคืนของวิธี HashCode เริ่มต้นของพวกเขาจะแตกต่างกัน
มาดูตัวอย่างที่เฉพาะเจาะจง:
rectobject วัตถุ: แพ็คเกจ com.weijia.demo; ชั้นเรียนสาธารณะ rectobject {public int x; สาธารณะ int y; public rectobject (int x, int y) {this.x = x; this.y = y; } @Override สาธารณะ int hashCode () {สุดท้าย int prime = 31; int ผลลัพธ์ = 1; result = prime * result + x; ผลลัพธ์ = Prime * ผลลัพธ์ + y; ผลการกลับมา; } @Override บูลีนสาธารณะเท่ากับ (Object obj) {ถ้า (this == obj) คืนค่าจริง; ถ้า (obj == null) ส่งคืนเท็จ; ถ้า (getClass ()! = obj.getClass ()) ส่งคืนเท็จ; ขั้นสุดท้าย rectobject อื่น ๆ = (rectobject) obj; if (x! = other.x) {return false; } ถ้า (y! = อื่น ๆ ) {return false; } return true; - เราแทนที่วิธีการ HashCode และเท่ากับในวัตถุคลาสแม่และดูว่าในวิธีการ HashCode และ Equals หากค่า X และ Y ของวัตถุ rectobject ทั้งสองมีค่าเท่ากันค่า hashcode ของพวกเขาจะเท่ากันและเท่ากับผลตอบแทนที่แท้จริง
นี่คือรหัสทดสอบ:
แพ็คเกจ com.weijia.demo; นำเข้า java.util.hashset; การสาธิตคลาสสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {hashset <rectobject> set = new hashset <rectobject> (); rectobject r1 = rectobject ใหม่ (3,3); rectobject r2 = rectobject ใหม่ (5,5); rectobject r3 = rectobject ใหม่ (3,3); set.add (R1); set.add (R2); set.add (R3); set.add (R1); System.out.println ("ขนาด:"+set.size ()); - เราเก็บวัตถุสี่ชิ้นไว้ใน HashSet และพิมพ์ขนาดของชุดคอลเลกชัน ผลลัพธ์คืออะไร?
ผลการทำงาน: ขนาด: 2
ทำไมถึง 2? นี่เป็นเรื่องง่ายมากเพราะเราเขียนวิธี HashCode ใหม่ของคลาส rectobject ตราบใดที่ค่าแอตทริบิวต์ x และ y ของวัตถุ rectobject มีค่าเท่ากันดังนั้นค่า hashcode ก็จะเท่ากัน ก่อนอื่นเปรียบเทียบค่า HashCode ค่าแอตทริบิวต์ x และ y ของวัตถุ R1 และ R2 ไม่เท่ากันดังนั้น hashcodes ของพวกเขาจึงแตกต่างกันดังนั้นวัตถุ R2 สามารถใส่ได้ แต่ค่าแอตทริบิวต์ X และ Y ของวัตถุ R3 จะเหมือนกับค่าแอตทริบิวต์ของวัตถุ R1 ดังนั้น HashCode จึงเท่ากัน ในเวลานี้เราเปรียบเทียบวิธี Equals ของ R1 และ R3 เนื่องจากค่า X และ Y ของทั้งสองมีค่าเท่ากันดังนั้นวัตถุ R1 และ R3 จึงเท่ากันดังนั้น R3 จึงไม่สามารถใส่ได้นอกจากนี้การเพิ่ม R1 ในตอนท้ายจึงไม่ได้เพิ่มดังนั้นจึงมีวัตถุเพียงสองชิ้น R1 และ R2 ในชุด
ต่อไปเราแสดงความคิดเห็นวิธีการ HashCode ในวัตถุ rectobject นั่นคือเราไม่ได้แทนที่วิธี HashCode ในวัตถุวัตถุและเรียกใช้รหัส:
ผลการทำงาน: ขนาด: 3
ผลลัพธ์นี้ก็ง่ายมาก ก่อนอื่นให้ตัดสิน HashCode ของวัตถุ R1 และวัตถุ R2 เนื่องจากวิธีการ HashCode ในวัตถุส่งคืนผลลัพธ์การแปลงของที่อยู่หน่วยความจำท้องถิ่นของวัตถุ HashCode ของวัตถุอินสแตนซ์ที่แตกต่างกันจึงแตกต่างกัน ในทำนองเดียวกันเนื่องจาก hashcode ของ R3 และ R1 ก็ไม่เท่ากัน แต่ R1 == R1 ดังนั้นในชุดสุดท้ายมีวัตถุเพียงสามวัตถุ R1, R2 และ R3 ดังนั้นขนาดจึงคือ 3
ต่อไปเราแสดงความคิดเห็นเนื้อหาของวิธี Equals ในวัตถุ rectobject ส่งคืนเท็จโดยตรงโดยไม่ต้องแสดงความคิดเห็นวิธี HashCode และเรียกใช้รหัส:
ผลการทำงาน: ขนาด: 3
ผลลัพธ์นี้ค่อนข้างคาดไม่ถึงมาวิเคราะห์กันเถอะ:
ขั้นแรกวัตถุของ R1 และ R2 เปรียบเทียบ HashCode ซึ่งไม่เท่ากันดังนั้น R2 จึงถูกใส่ลงในชุดจากนั้นดูที่วิธีการ HashCode ของ R3 และเปรียบเทียบ R1 และ R3 ซึ่งเท่ากันแล้วเปรียบเทียบวิธีการเท่ากับ เนื่องจากวิธี Equals มักจะส่งคืนเท็จเสมอ R1 และ R3 ก็ไม่เท่ากันและไม่จำเป็นต้องพูดถึง R3 และ R2 hashcodes ของทั้งสองของพวกเขาไม่เท่ากันดังนั้น R3 จึงถูกนำไปตั้งค่าแล้วดูที่ R4 และเปรียบเทียบ R1 และ R4 พบว่า hashcodes มีค่าเท่ากัน เมื่อเปรียบเทียบวิธีการเท่ากับเนื่องจากเท่ากับผลตอบแทนเท็จ R1 และ R4 ไม่เท่ากัน R2 และ R4 เดียวกันก็ไม่เท่ากันและ R3 และ R4 ก็ไม่เท่ากันดังนั้น R4 จึงสามารถวางไว้ในชุดชุดดังนั้นผลลัพธ์ควรเป็นขนาด: 4 ดังนั้นทำไมจึงเป็น 3?
ในเวลานี้เราต้องตรวจสอบซอร์สโค้ดของ HashSet นี่คือซอร์สโค้ดของวิธีการเพิ่มใน HashSet:
/*** เพิ่มองค์ประกอบที่ระบุในชุดนี้หากยังไม่ปรากฏ * อย่างเป็นทางการมากขึ้นเพิ่มองค์ประกอบที่ระบุ <tt> e </tt> ในชุดนี้หาก * ชุดนี้ไม่มีองค์ประกอบ <tt> e2 </tt> เช่นนั้น * <tt> (e == null? e2 == null: e.equals (e2)) </tt> * หากชุดนี้มีองค์ประกอบอยู่แล้วการโทรจะออกจากชุด * ไม่เปลี่ยนแปลงและส่งคืน <tt> false </tt> * * @param e องค์ประกอบที่จะเพิ่มในชุดนี้ * @return <tt> true </ tt> หากชุดนี้ยังไม่มีองค์ประกอบ * ที่ระบุ */ บูลีนสาธารณะเพิ่ม (e e) {return map.put (e, ปัจจุบัน) == null; - ที่นี่เราจะเห็นว่า HashSet ถูกนำไปใช้จริงตาม HashMap เรากำลังคลิกที่วิธีการของ HashMap ซอร์สโค้ดมีดังนี้:
/*** เชื่อมโยงค่าที่ระบุกับคีย์ที่ระบุในแผนที่นี้ * หากแผนที่ก่อนหน้านี้มีการแมปสำหรับคีย์ค่าเก่า * จะถูกแทนที่ * * คีย์คีย์ @param ซึ่งค่าที่ระบุจะเกี่ยวข้อง * @param value ค่าที่จะเชื่อมโยงกับคีย์ที่ระบุ * @@Return ค่าก่อนหน้านี้ที่เกี่ยวข้องกับ <tt> คีย์ </tt> หรือ * <tt> null </tt> หากไม่มีการแม็พสำหรับ <tt> คีย์ </tt> * (a <tt> null </tt> กลับยังสามารถระบุได้ว่าแผนที่ * ก่อนหน้านี้เกี่ยวข้องกับ <tt> null </tt> ด้วย <tt> คีย์ </tt>.) */public v ใส่ (k key, v value) {ถ้า (key == null) ส่งคืน putfornullkey (ค่า); int hash = hash (คีย์); int i = indexfor (แฮช, table.length); สำหรับ (รายการ <k, v> e = ตาราง [i]; e! = null; e = e.next) {วัตถุ k; if (e.hash == hash && ((k = e.key) == key || key.equals (k))) {v oldValue = e.value; e.value = ค่า; E.RecordAccess (นี่); กลับ OldValue; }} ModCount ++; Addentry (แฮช, คีย์, ค่า, i); คืนค่า null; - มาดูเงื่อนไขการตัดสินของ IF
ก่อนอื่นเราจะพิจารณาว่า hashcode นั้นเท่ากันหรือไม่ หากไม่เท่ากันให้ข้ามไปโดยตรง หากเท่ากันให้เปรียบเทียบว่าวัตถุทั้งสองนี้มีค่าเท่ากันหรือวิธีการเท่ากับของวัตถุทั้งสองนี้ เนื่องจากมีการดำเนินการหรือดำเนินการตราบใดที่หนึ่งเป็นจริงเราจึงสามารถอธิบายได้ที่นี่ ในความเป็นจริงขนาดของชุดข้างต้นคือ 3 เนื่องจาก R1 สุดท้ายไม่ได้ใส่และคิดว่า R1 == R1 กลับมาเป็นจริงดังนั้นจึงไม่ได้ใส่ดังนั้นขนาดของชุดคือ 3 ถ้าเราตั้งวิธี HashCode ให้กลับเท็จเสมอ
สุดท้ายมาดูการรั่วไหลของหน่วยความจำที่เกิดจาก HashCode: ดูที่รหัส:
แพ็คเกจ com.weijia.demo; นำเข้า java.util.hashset; การสาธิตคลาสสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {hashset <rectobject> set = new hashset <rectobject> (); rectobject r1 = rectobject ใหม่ (3,3); rectobject r2 = rectobject ใหม่ (5,5); rectobject r3 = rectobject ใหม่ (3,3); set.add (R1); set.add (R2); set.add (R3); r3.y = 7; System.out.println ("ขนาดก่อนลบ:"+set.size ()); set.remove (R3); System.out.println ("ขนาดหลังจากการลบ:"+set.size ()); - ผลการทำงาน:
ขนาดก่อนลบ: 3
ขนาดที่ถูกลบ: 3
เร่งด่วนฉันพบปัญหาและมันเป็นปัญหาใหญ่ เราเรียกว่าลบเพื่อลบวัตถุ R3 โดยคิดว่ามันถูกลบ แต่ในความเป็นจริงมันไม่ได้ถูกลบ สิ่งนี้เรียกว่าการรั่วไหลของหน่วยความจำซึ่งเป็นวัตถุที่ไม่ได้ใช้ แต่ยังอยู่ในความทรงจำ ดังนั้นหลังจากที่เราทำงานหลายครั้งหน่วยความจำก็จะระเบิด ดูที่ซอร์สโค้ดของการลบ:
/*** ลบองค์ประกอบที่ระบุออกจากชุดนี้หากมีอยู่ * อย่างเป็นทางการมากขึ้นลบองค์ประกอบ <tt> e </tt> เช่นนั้น * <tt> (o == null? e == null: o.equals (e)) </tt>, * หากชุดนี้มีองค์ประกอบดังกล่าว ส่งคืน <tt> true </tt> ถ้า * ชุดนี้มีองค์ประกอบ (หรือเทียบเท่าถ้าชุดนี้เปลี่ยนเป็นผลมาจากการโทร) (ชุดนี้จะไม่มีองค์ประกอบ * เมื่อการโทรกลับมา) * * @param o วัตถุที่จะลบออกจากชุดนี้ถ้ามี * @return <tt> true </ tt> หากชุดมีองค์ประกอบที่ระบุ */ บูลีนสาธารณะลบ (วัตถุ o) {return map.remove (o) == ปัจจุบัน; - จากนั้นดูที่ซอร์สโค้ดของวิธีการลบ:
/*** ลบการแมปสำหรับคีย์ที่ระบุจากแผนที่นี้หากมีอยู่ * * คีย์คีย์ @param ที่มีการแมปจะถูกลบออกจากแผนที่ * @return ค่าก่อนหน้านี้ที่เกี่ยวข้องกับ <tt> คีย์ </tt> หรือ * <tt> null </tt> หากไม่มีการแมปสำหรับ <tt> คีย์ </tt> * (A <tt> null </tt> return ยังสามารถระบุได้ว่าแผนที่ * ก่อนหน้านี้ที่เกี่ยวข้อง <tt> null </tt> ด้วย <tt> คีย์ </tt>.) */สาธารณะ v ลบ (คีย์วัตถุ) {รายการ <k, v> e = removeentryforkey (คีย์); return (e == null? null: e.value); - ลองดูที่ซอร์สโค้ดวิธี removeentryforkey:
/** * ลบและส่งคืนรายการที่เกี่ยวข้องกับคีย์ที่ระบุ * ใน HASHMAP ส่งคืนค่า null ถ้า hashmap ไม่มีการแมป * สำหรับคีย์นี้ */ รายการสุดท้าย <k, v> removeentryforkey (คีย์วัตถุ) {int hash = (key == null)? 0: แฮช (กุญแจ); int i = indexfor (แฮช, table.length); รายการ <k, v> prev = ตาราง [i]; รายการ <k, v> e = prev; ในขณะที่ (e! = null) {entry <k, v> next = e.next; วัตถุ K; if (e.hash == hash && ((k = e.key) == key || (key! = null && key.equals (k)))) {modcount ++; ขนาด--; if (prev == e) ตาราง [i] = ถัดไป; else prev.next = ถัดไป; E.recordremoval (นี่); กลับ E; } prev = e; e = ถัดไป; } return e; - เราเห็นว่าเมื่อเรียกใช้วิธีการลบเราจะใช้ค่าแฮชโฟตอนก่อนของวัตถุเพื่อค้นหาวัตถุแล้วลบออก ปัญหานี้เป็นเพราะเราได้ปรับเปลี่ยนค่าของแอตทริบิวต์ y ของวัตถุ R3 และเนื่องจากวิธีการ HashCode ของวัตถุ rectobject มีค่า y ที่เข้าร่วมในการดำเนินการ hashcode ของวัตถุ R3 มีการเปลี่ยนแปลงดังนั้น R3 จึงไม่พบในวิธีการลบดังนั้นการลบจึงล้มเหลว นั่นคือ HashCode ของ R3 มีการเปลี่ยนแปลง แต่ที่เก็บของที่เก็บยังไม่ได้รับการอัปเดตและยังอยู่ในตำแหน่งเดิมดังนั้นเมื่อเราใช้ hashcode ใหม่เพื่อค้นหาเราจะไม่พบแน่นอน
ในความเป็นจริงวิธีการข้างต้นนั้นง่ายมากที่จะนำไปใช้: ดังที่แสดงในรูป:
ตารางแฮชเชิงเส้นที่ง่ายมากฟังก์ชั่นแฮชที่ใช้คือ mod ซอร์สโค้ดมีดังนี้:
/*** return index สำหรับรหัสแฮช h */ indext index สำหรับ (int h, ความยาว int) {return h & (length-1); - นี่คือการดำเนินการ MOD แต่การดำเนินการประเภทนี้มีประสิทธิภาพมากกว่าการดำเนินการ %
1,2,3,4,5 หมายถึงผลลัพธ์ของ mod และแต่ละองค์ประกอบสอดคล้องกับโครงสร้างรายการที่เชื่อมโยง ดังนั้นหากคุณต้องการลบรายการ <k, v> คุณจะได้รับ hashcode ก่อนเพื่อรับโหนดส่วนหัวของรายการที่เชื่อมโยงแล้ววนซ้ำผ่านรายการที่เชื่อมโยง หาก HashCode และ Equals เท่ากันให้ลบองค์ประกอบนี้
การรั่วไหลของหน่วยความจำข้างต้นบอกฉันว่า: หากเราเข้าร่วมในการทำงานของ HashCode ของค่าแอตทริบิวต์ของวัตถุเราไม่สามารถแก้ไขค่าแอตทริบิวต์ของมันได้เมื่อลบออกมิฉะนั้นปัญหาร้ายแรงจะเกิดขึ้น
ในความเป็นจริงเรายังสามารถดูวิธีการ HashCode และวิธีการเท่ากับประเภทวัตถุที่สอดคล้องกับ 8 ชนิดข้อมูลพื้นฐาน
ในหมู่พวกเขา hashcode ของประเภทพื้นฐานใน 8 นั้นง่ายมากที่จะส่งคืนขนาดตัวเลขโดยตรง วัตถุสตริงนั้นผ่านวิธีการคำนวณที่ซับซ้อน แต่วิธีการคำนวณนี้สามารถตรวจสอบได้ว่าหากค่าของสตริงนี้เท่ากันแฮชโฟนของพวกเขาจะเท่ากัน 8 ประเภทพื้นฐานของวิธีการเท่ากับวิธีการเปรียบเทียบค่าตัวเลขโดยตรงและวิธีการประเภทสตริงเท่ากับวิธีการเปรียบเทียบค่าของสตริง
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น