1. ทำไม hashcode ()?
องค์ประกอบในชุดชุดนั้นไม่เป็นระเบียบและไม่สามารถทำซ้ำได้ดังนั้นอะไรคือพื้นฐานสำหรับการตัดสินว่าสององค์ประกอบซ้ำแล้วซ้ำอีก? "แน่นอน Object.equal () ใช้เพื่อเปรียบเทียบว่าวัตถุนั้นเท่ากันหรือไม่" ลิงบางตัวกล่าว อย่างไรก็ตามมีวัตถุจำนวนมากในชุดและจำนวนการเปรียบเทียบองค์ประกอบของวัตถุที่เพิ่มเข้ามาในชุดชุดจะค่อยๆเพิ่มขึ้นอย่างมากลดประสิทธิภาพของการทำงานของโปรแกรม Java ใช้อัลกอริทึมการแฮช (เรียกอีกอย่างว่าการแฮชอัลกอริทึม) เพื่อแก้ปัญหานี้ วัตถุ (หรือข้อมูล) ถูกแมปโดยตรงไปยังที่อยู่ตามอัลกอริทึมเฉพาะและประสิทธิภาพการเข้าถึงของวัตถุได้รับการปรับปรุงอย่างมาก ด้วยวิธีนี้เมื่อชุดชุดที่มีองค์ประกอบจำนวนมากจำเป็นต้องเพิ่มองค์ประกอบ (วัตถุ) การโทรครั้งแรก HashCode () ขององค์ประกอบนี้และคุณสามารถจัดตำแหน่งตำแหน่งที่เก็บข้อมูลจริงขององค์ประกอบนี้ได้ในครั้งเดียว หากไม่มีองค์ประกอบที่ตำแหน่งนี้หมายความว่าวัตถุจะถูกเก็บไว้ในชุดคอลเลกชันเป็นครั้งแรกและวัตถุจะถูกเก็บไว้โดยตรงที่ตำแหน่งนี้ หากมีวัตถุที่ตำแหน่งนี้ให้โทร Equal () เพื่อดูว่าวัตถุทั้งสองเท่ากันหรือไม่ หากสิ่งเดียวกันเป็นจริงให้ทิ้งองค์ประกอบและไม่มีอยู่จริง หากไม่เท่ากันแฮชกับที่อยู่อื่น
2. ใช้ hashcode () ได้อย่างไร?
ภาษา Java มีข้อกำหนดห้าประการที่ต้องปฏิบัติตาม () ในการออกแบบลิง
สมมาตร. ถ้า A.equal (b) ส่งคืน "true" ดังนั้น b.equal (a) จะต้องส่งคืน "true" ด้วย
สะท้อนแสง a.equal (a) ต้องกลับ "จริง"
สกรรมกริยา ถ้า A.equal (b) ส่งคืน "true" และ b.equal (c) ส่งคืน "true" ดังนั้น c.equal (a) จะต้องส่งคืน "true"
ความสอดคล้อง ถ้า A.equal (b) ส่งคืน "จริง" ตราบใดที่เนื้อหาของ A และ B ยังคงไม่เปลี่ยนแปลงไม่ว่า A.equal (b) จะต้องกลับ "จริง" กี่ครั้ง
ไม่ว่าในกรณีใด A.Equals (NULL) จะส่งคืน "เท็จ" เสมอ; A.Equals (วัตถุประเภทต่าง ๆ และก) จะส่งคืน "เท็จ" เสมอ
ความสัมพันธ์ระหว่างค่าส่งคืนของ HashCode () และ Equals ()
ถ้า A.Equals (b) ส่งคืน "true" ดังนั้น hashcode () ของ A และ B จะต้องเท่ากัน
หาก A.Equals (b) ส่งคืน "เท็จ" ดังนั้น HashCode () ของ A และ B อาจเท่ากับหรืออาจไม่เท่ากัน
นี่คือตัวอย่าง ในการพัฒนาซอฟต์แวร์ที่แท้จริงจะเป็นการดีที่สุดที่จะเขียนสองวิธีนี้ใหม่
พนักงานชั้นเรียนสาธารณะ {int EmployeeId; ชื่อสตริง; // วิธีอื่นจะอยู่ที่นี่ @Override บูลีนสาธารณะเท่ากับ (Object obj) {ถ้า (obj == สิ่งนี้) กลับมาจริง พนักงาน EMP = (พนักงาน) OBJ; if (EmployeeId.equals (emp.getemployeeId ()) && name == emp.getName ()) ส่งคืนจริง; กลับเท็จ; } @Override สาธารณะ int hashCode () {int hash = 1; แฮช = แฮช * 17 + พนักงาน; hash = hash * 31 + name.hashcode (); คืนแฮช; -3. ต่อไปนี้เป็นจุดเน้นที่วิธีการใช้งาน HashCode () ของคลาสที่ใช้กันทั่วไป
hascode () ของคลาสสตริง
public int hashCode () {int h = hash; if (h == 0) {int ปิด = ออฟเซ็ต; ถ่าน val [] = ค่า; int len = นับ; สำหรับ (int i = 0; i <len; i ++) {h = 31*h+val [ปิด ++]; } hash = h; } return h; -สิ่งที่น่าสนใจที่สุดเกี่ยวกับรหัสนี้คือวิธีการใช้งานของแฮช ค่าแฮชที่คำนวณได้ขั้นสุดท้ายคือ:
S [0] 31N-1 + S [1] 31N-2 + … + S [N-1]
s [i] เป็นอักขระ i-th ของสตริงและ n คือความยาวของสตริง แล้วทำไมต้องใช้ 31 ที่นี่แทนตัวเลขอื่น ๆ ?
31 เป็นหมายเลขสำคัญคี่ หากตัวคูณเป็นตัวเลขที่สม่ำเสมอและการคูณล้นข้อมูลจะหายไปเนื่องจากการคูณด้วย 2 เทียบเท่ากับการดำเนินการเปลี่ยน ประโยชน์ของการใช้ตัวเลขที่สำคัญไม่ชัดเจน แต่ผลลัพธ์แฮชถูกใช้ตามอัตภาพเพื่อคำนวณผลลัพธ์แฮช 31 มีคุณสมบัติที่ดีซึ่งก็คือการใช้การเปลี่ยนแปลงและการลบแทนการคูณเพื่อให้ได้ประสิทธิภาพที่ดีขึ้น: 31*i == (i << 5) -i VMS สามารถปรับการเพิ่มประสิทธิภาพนี้ให้เสร็จสมบูรณ์โดยอัตโนมัติ (จาก Java ที่มีประสิทธิภาพ)
hascode () ของคลาสวัตถุ
HashCode () เป็นวิธีการดั้งเดิมในคลาสวัตถุ วิธีเรียกวิธีการดั้งเดิม?
hashcode int สาธารณะ ();
คลาสวิธีการดั้งเดิมของคลาสวัตถุสามารถพบได้ที่นี่ โปรดอ่านบล็อกอื่นสำหรับการวิเคราะห์เชิงลึก
jninativeMethod แบบคงที่ [] = {{"hashCode", "() i", (void *) & jvm_ihashcode}, {"รอ", "(j) v", (void *) & jvm_monitorwait}, {"notify", "() "() v", (void *) & jvm_monitornotifyall}, {"clone", "() ljava/lang/object;", (void *) & jvm_clone},};ซอร์สโค้ดรวมถึง getClass () (ดู LINE58) ฯลฯ HashCode () (ดู LINE43) ถูกกำหนดเป็นตัวชี้ไปยัง JVM_IHASHCODE
JVM.CPP กำหนดฟังก์ชัน JVM_IHASHCODE (บรรทัด 504) ฟังก์ชั่นนี้เรียกว่า ObjectSynchronizer :: FasthashCode ซึ่งถูกกำหนดใน synchronizer.cpp สำหรับการใช้งาน FastHashCode ในบรรทัด 576 และ GET_NEXT_HASH ในบรรทัด 530 คุณสามารถอ้างถึงการใช้งานของ FastHashCode ในบรรทัด 576 และ GET_NEXT_HASH ในบรรทัด 530