เราทุกคนรู้ว่าภาษา Java นั้นมุ่งเน้นไปที่วัตถุอย่างสมบูรณ์ ใน Java วัตถุทั้งหมดได้รับการสืบทอดจากคลาสวัตถุ
วิธี Equals เปรียบเทียบที่อยู่ที่ชี้ไปที่การอ้างอิงของสองวัตถุ HashCode เป็นวิธีการในท้องถิ่นซึ่งส่งคืนค่าที่อยู่วัตถุ มีสองวิธีในคลาส Ojbect เท่ากับและ hashcode สองวิธีนี้ใช้เพื่อเปรียบเทียบว่าวัตถุทั้งสองเท่ากันหรือไม่
ทำไมเราต้องแทนที่วิธี HashCode ในขณะที่เขียนวิธี Equals ใหม่
มันสามารถเข้าใจได้ดังนี้: หลังจากการเขียนวิธี Equals ใหม่ตรรกะทางธุรกิจสำหรับการตัดสินความเท่าเทียมกันของวัตถุจะเปลี่ยนไป ผู้ออกแบบชั้นเรียนไม่ต้องการเปรียบเทียบความเท่าเทียมกันของวัตถุทั้งสองโดยการเปรียบเทียบที่อยู่หน่วยความจำ มันไม่มีความหมายที่จะเปรียบเทียบตามที่อยู่ ดังนั้นมันก็เปลี่ยนไปด้วยกัน
อีกเหตุผลมาจากคอลเลกชัน มาพูดถึงเรื่องนี้ช้าๆด้านล่าง ~
ตัวอย่างเช่น:
ในโรงเรียนมันผ่านรหัสนักเรียนเพื่อตรวจสอบว่าบุคคลนี้เป็นของหรือไม่
สถานการณ์ในรหัสด้านล่างคือรายการบันทึกนักเรียนหมายเลขนักเรียน 123 ได้รับมอบหมายให้นักเรียนทอมหมายเลขนักเรียน 456 ได้รับมอบหมายให้นักเรียนเจอร์รี่และหมายเลขนักเรียน 123 ได้รับมอบหมายให้ลิลลี่โดยไม่ได้ตั้งใจ อย่างไรก็ตามหมายเลขนักเรียนเดียวกันไม่ควรเกิดขึ้นในระหว่างกระบวนการลงทะเบียนสถานะนักเรียน
ไม่สามารถเพิ่มวัตถุที่ซ้ำกันได้ทั้งนี้ขึ้นอยู่กับข้อกำหนดของสถานการณ์
การทดสอบระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {นักเรียน stu = นักเรียนใหม่ (123, "tom"); hashset <student> set = new hashset <> (); set.add (stu); set.add (นักเรียนใหม่ (456, "Jerry")); ในขณะที่ (iterator.hasnext ()) {นักเรียนนักเรียน = iterator.next (); System.out.println (student.getStunum () + "---" + student.getName ());}}}; นักเรียนชั้นเรียน {ส่วนตัว int stunum; ชื่อสตริงส่วนตัว; นักเรียนสาธารณะ (int stunum, ชื่อสตริง) {this.stunum = stunum; NAME;}@overridePublic Boolean เท่ากับ (Object obj) {ถ้า (this == obj) return true; ถ้า (OBJ instanceof นักเรียน) {ถ้า (this.getStunum () == ((นักเรียน) OBJ). getStunum ()) กลับจริง; ผลลัพธ์คือ:
123 --- ลิลลี่
456 --- เจอรี่
123 --- ทอม
จากผลลัพธ์เราพบว่าการกำหนดหมายเลขนักเรียน 123 ให้กับลิลลี่ประสบความสำเร็จอีกครั้ง เกิดอะไรขึ้น?
ลองดูที่วิธีเพิ่มของ HashSet:
บูลีนสาธารณะเพิ่ม (e e) {return map.put (e, ปัจจุบัน) == null;} ในความเป็นจริง HashSet ถูกนำไปใช้ผ่าน HASHMAP ดังนั้นเราจึงติดตามวิธีการวาง HASHMAP:
Public V Put (k key, v value) {ถ้า (table == emport_table) {inflatetable (threshold);} ถ้า (key == null) return putfornullkey (ค่า); int hash = hash (key); int i = indexfor (hash, table.length); hash && ((k = e.key) == key || key.equals (k))) {v oldValue = e.value; e.value = value; e.recordaccess (นี่); return oldValue;}} modCount ++;1. ตามคีย์นั่นคือวัตถุที่จะเพิ่มโดย HashSet รับ HashCode และ HashCode จะใช้ในการดำเนินการบิตเฉพาะเพื่อรับรหัสแฮช
2. ใช้ตำแหน่งรหัสแฮชเพื่อค้นหาตัวห้อยอาร์เรย์เพื่อรับส่วนหัวลิงค์ของรายการที่เชื่อมโยง
3. สำรวจรายการที่เชื่อมโยงเพื่อดูว่ามีคีย์เดียวกันหรือไม่ พื้นฐานสำหรับการตัดสินคือ e.hash == hash && ((k = e.key) == key || key.equals (k)) เมื่อเพิ่มลิลลี่เนื่องจากวิธีการที่ถูกเขียนใหม่เงื่อนไขที่สองควรเป็นจริงเมื่อข้ามทอม แต่เนื่องจากวิธีการ HashCode ยังคงใช้คลาสหลัก HashCode ของ Tom และ Lily นั้นแตกต่างกันนั่นคือรหัสแฮชจึงแตกต่างกันและเงื่อนไขแรกเป็นเท็จ ที่นี่เราเข้าใจว่าวัตถุทั้งสองนั้นแตกต่างกันดังนั้น HashSet จะเพิ่มลิลลี่ให้สำเร็จ
เหตุผลก็คือวิธีการ HashCode ไม่ได้เขียนใหม่ นี่คือการดัดแปลง:
การทดสอบระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {นักเรียน stu = นักเรียนใหม่ (123, "tom"); hashset <student> set = new hashset <> (); set.add (stu); set.add (นักเรียนใหม่ (456, "Jerry")); ในขณะที่ (iterator.hasnext ()) {นักเรียนนักเรียน = iterator.next (); System.out.println (student.getStunum () + "---" + student.getName ());}}}; นักเรียนชั้นเรียน {ส่วนตัว int stunum; ชื่อสตริงส่วนตัว; นักเรียนสาธารณะ (int stunum, ชื่อสตริง) {this.stunum = stunum; ชื่อ;}@boolean overridepublic เท่ากับ (object obj) {ถ้า (this == obj) return true; ถ้า (OBJ Instanceof นักเรียน) {ถ้า (this.getStunum () == ((นักเรียน) obj .getStunum เอาท์พุท:
456 --- เจอรี่
123 --- ทอม
เขียนวิธี HashCode ใหม่และส่งคืนหมายเลขนักเรียน ตกลงเสร็จแล้ว
บางคนอาจสงสัย, e.hash == hash && ((k = e.key) == key || key.equals (k)) ค่อนข้างซับซ้อน? ฉันคิดว่ามันเพียงพอที่จะใช้วิธีการเท่ากับ ทำไมคุณต้องตัดสิน HashCode ในครั้งเดียว
เนื่องจากเมื่อการสำรวจและตัดสินในโครงสร้างรายการที่เชื่อมโยงของ HashMap ตรรกะทางธุรกิจของวิธีการเขียนใหม่นั้นมีความซับซ้อนมากขึ้นเพื่อเปรียบเทียบว่าวัตถุนั้นเท่ากันในสถานการณ์เฉพาะและตรรกะทางธุรกิจของการวนซ้ำจะส่งผลต่อประสิทธิภาพการค้นหาหรือไม่ ดังนั้นที่นี่เราจึงตัดสิน HashCode ก่อน ตราบใดที่ HashCode ยังไม่เท่ากันคุณจะเล่นเสร็จและไม่จำเป็นต้องเรียกความซับซ้อนเท่ากับอีกต่อไป ปรับปรุงประสิทธิภาพของ Hashmap ในระดับใหญ่
ดังนั้นวิธีการ HashCode คือการอนุญาตให้เราใช้คลาสการรวบรวมเช่น HASHMAP ตามปกติเนื่องจาก HASHMAP กำหนดว่าวัตถุมีความเท่าเทียมกันทั้ง HashCode และการเปรียบเทียบเท่ากับ การใช้งานนี้คือการปรับปรุงประสิทธิภาพของ HASHMAP