Boolean.hashCode ()


122

hashCode()วิธีการของการเรียนแบบบูลจะดำเนินการเช่นนี้

public int hashCode() {
    return value ? 1231 : 1237;
}

ทำไมถึงใช้ 1231 และ 1237? ทำไมไม่เป็นอย่างอื่น?


1
ตัวเลขทั้งสองนี้เป็นจำนวนเฉพาะที่มีขนาดใหญ่เพียงพอ โปรดอ่านบทความเกี่ยวกับ Hash Tableใน Wikipedia สำหรับข้อมูลเพิ่มเติม
Boris Pavlović

คำตอบ:


140

1231 และ 1237 เป็นเพียงสอง (ขนาดใหญ่พอ) ตัวเลขที่สำคัญโดยพลการ จำนวนเฉพาะที่มีขนาดใหญ่อีกสองตัวจะทำได้ดี

ทำไมต้องมีรอบ?
สมมติว่าเป็นครั้งที่สองที่เราหยิบตัวเลขคอมโพสิต (ไม่ใช่เฉพาะ) กล่าวว่า 1000 และ 2000 เมื่อใส่ booleans ลงในตารางแฮชจริงและเท็จจะไปลงในถัง1000 % Nรับผิดชอบ2000 % N(ซึ่งNคือจำนวนของถัง)

ตอนนี้สังเกตว่า

  • 1000 % 8 ถังเดียวกับ 2000 % 8
  • 1000 % 10 ถังเดียวกับ 2000 % 10
  • 1000 % 20 ถังเดียวกับ 2000 % 20
  • ....

กล่าวอีกนัยหนึ่งมันจะนำไปสู่การชนกันหลายครั้ง

เนื่องจากการแยกตัวประกอบของ 1000 (2 3 , 5 3 ) และการแยกตัวประกอบของ 2000 (2 4 , 5 3 ) มีปัจจัยร่วมมากมาย ดังนั้นจึงมีการเลือกจำนวนเฉพาะเนื่องจากไม่น่าจะมีปัจจัยร่วมกับขนาดถัง

ทำไมช่วงใหญ่ 2 และ 3 จะไม่ทำเหรอ?
เมื่อคำนวณรหัสแฮชสำหรับออบเจ็กต์แบบผสมมักจะต้องเพิ่มรหัสแฮชสำหรับส่วนประกอบ หากใช้ค่าที่น้อยเกินไปในชุดแฮชที่มีที่เก็บข้อมูลจำนวนมากมีความเสี่ยงที่จะลงเอยด้วยการกระจายวัตถุที่ไม่สม่ำเสมอ

การชนมีความสำคัญหรือไม่? บูลีนมีค่าต่างกันสองค่าใช่หรือไม่
แผนที่สามารถมีบูลีนร่วมกับวัตถุอื่น ๆ นอกจากนี้ตามที่ Drunix ชี้ให้เห็นวิธีทั่วไปในการสร้างฟังก์ชันแฮชของออบเจ็กต์คอมโพสิตคือการนำการใช้งานโค้ดแฮชคอมโพเนนต์ย่อยกลับมาใช้ใหม่ซึ่งในกรณีนี้เป็นการดีที่จะคืนค่าช่วงเวลาที่มาก

คำถามที่เกี่ยวข้อง:


1
ฉันคิดว่าสิ่งเหล่านี้มีขนาดใหญ่พอสมควร ในการรับ gcd ที่มากกว่า 1 คุณต้องมีที่2*1231 = 2462เก็บข้อมูลอย่างน้อย การชนกันเป็นปัญหาในสถานการณ์เช่นนี้หรือไม่?
aioobe

2
น่าสนใจแม้ว่าพวกเขาจะไม่ "ใหญ่พอสมควร" เมื่อพิจารณาถึงสิ่งที่สามารถเข้ากับ int ได้ ฉันคิดว่าพวกมันใหญ่พอที่จะทำงานได้ดีกับ JDK Hashtable แต่ก็ยังเล็กพอที่จะลดต้นทุนการคำนวณให้เหลือน้อยที่สุด
Thilo

2
ใช่มันหลงฉันเกินไปที่พวกเขาไม่ได้ว่ามีขนาดใหญ่ แต่คุณเชื่อไหมว่ามีค่าใช้จ่ายที่สูงกว่าและมีราคาสูงกว่า
aioobe

3
@Thilo คุณต้องมีจำนวน 1231 * 1237 = 1,522,747 ถังก่อนที่จะชนกันซึ่งมีขนาดใหญ่เพียงพอ
วงล้อประหลาด

2
ฉันจะบอกว่าการนำไปสู่การชนกับจำนวนที่เก็บข้อมูลนั้นไม่ได้เป็นปัญหากับบูลีน แต่เป็นการสร้างทั่วไปในการรับ hascode ของออบเจ็กต์คอมโพสิตกล่าวคือโดยการคูณแฮชโค้ดของส่วนประกอบกับค่าคงที่บางส่วนและเพิ่มขึ้น
Drunix

2

นอกจากทั้งหมดที่กล่าวไว้ข้างต้นแล้วยังสามารถเป็นไข่อีสเตอร์ขนาดเล็กจากผู้พัฒนา:

จริง: 1231 => 1 + 2 + 3 + 1 = 7

7 - เป็นเลขนำโชคในประเพณีของยุโรป

เท็จ: 1237 => 1 + 2 + 3 + 7 = 13

13 (aka Devil's โหล) - เลขที่โชคร้าย

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