การใช้ hashCode ใน Java คืออะไร?


161

ใน Java ให้obj.hashCode()คืนค่าบางค่า การใช้รหัสแฮชนี้ในการเขียนโปรแกรมคืออะไร?


คำถามนี้เพิ่มรายละเอียดเพิ่มเติม stackoverflow.com/questions/18078779/…
MaheshVarma

1
คำอธิบายที่ดีให้ไว้ในโพสต์นี้ eclipsesource.com/blogs/2012/09/04/…
Vijay Vankhede

คำตอบ:


222

hashCode()จะใช้สำหรับการbucketingในHashการใช้งานที่ชอบHashMap, HashTable, HashSetฯลฯ

ค่าที่ได้รับจากhashCode()จะถูกใช้เป็นหมายเลขถังสำหรับจัดเก็บองค์ประกอบของชุด / แผนที่ หมายเลขถังนี้คือที่อยู่ขององค์ประกอบภายในชุด / แผนที่

เมื่อคุณทำcontains()มันจะใช้รหัสแฮชขององค์ประกอบจากนั้นมองหาที่ฝากข้อมูลที่รหัสแฮชชี้ไปที่ หากพบมากกว่า 1 องค์ประกอบในที่เก็บข้อมูลเดียวกัน (หลายวัตถุสามารถมีรหัสแฮชเดียวกันได้) จากนั้นจะใช้equals()วิธีการประเมินว่าวัตถุเท่ากันแล้วตัดสินใจว่าcontains()เป็นจริงหรือเท็จหรือตัดสินว่าองค์ประกอบอาจเป็น เพิ่มในชุดหรือไม่


28
สวัสดี Buddy .. คำตอบที่ดีมาก แต่ฉันพบลิงค์ที่น่าสนใจเหมือนกันพร้อมตัวอย่างที่เข้าใจง่าย: coderanch.com/t/321515/java/java/HashCode
Logicalj

ขอบคุณ Aishu ตอนนี้ฉันมีความรู้ที่ชัดเจนเกี่ยวกับ hashcode พร้อมคำอธิบายที่เกี่ยวข้องกับ bucket
Balasubramani

2
"หากพบมากกว่า 1 องค์ประกอบในที่เก็บข้อมูลเดียวกัน .. จากนั้นจะใช้การequals()ประเมินผล" ดังนั้นจะเกิดอะไรขึ้นหากพบรหัสองค์ประกอบแฮชที่ตรงกับองค์ประกอบเดียวเท่านั้นจะส่งคืนจริงหรือไม่ แต่เนื่องจากวัตถุหลาย ๆ ชิ้นสามารถมีรหัสแฮชเดียวกันดังนั้นจึงจำเป็นต้องเรียกใช้equals()เพื่อประเมินว่าองค์ประกอบที่ตรงกันเท่ากันมิฉะนั้นอาจทำให้คุณได้ผลลัพธ์ที่ไม่คาดคิดใช่ไหม
Saorikido

ฝากกัน hashcode เป็นวิธีการที่วัตถุเรียกเพื่อกำหนดลำดับการจัดเก็บแต่ละวัตถุในหน่วยความจำ หากวัตถุมีค่าเท่ากันแฮชโค้ดของพวกเขาจะต้องเท่ากัน (สนทนาของคำสั่งนี้เป็นเท็จ)
NoName

1
โปรแกรมเมอร์จะเรียกใช้hashCode()เมธอดด้วยตนเองในกรณีใด
พระคาร์ดินัล - Reinstate Monica

33

จากJavadoc :

ส่งคืนค่ารหัสแฮชสำหรับวัตถุ วิธีนี้ได้รับการสนับสนุนเพื่อประโยชน์ของ hashtables java.util.Hashtableเช่นผู้ให้บริการโดย

สัญญาทั่วไปhashCodeคือ:

  • เมื่อใดก็ตามที่มีการเรียกใช้บนวัตถุเดียวกันมากกว่าหนึ่งครั้งในระหว่างการดำเนินการของแอปพลิเคชัน Java hashCodeวิธีการจะต้องส่งกลับจำนวนเต็มเดียวกันอย่างสม่ำเสมอโดยไม่มีข้อมูลที่ใช้ในการเปรียบเทียบเท่ากับการแก้ไขวัตถุ จำนวนเต็มนี้ไม่จำเป็นต้องคงที่จากการเรียกใช้แอปพลิเคชันหนึ่งไปยังการเรียกใช้แอปพลิเคชันเดียวกันอีกครั้ง

  • หากวัตถุสองชิ้นมีค่าเท่ากันตามequals(Object)วิธีการการเรียกใช้hashCodeวิธีการกับวัตถุทั้งสองนั้นจะต้องให้ผลลัพธ์ที่เป็นจำนวนเต็มเหมือนกัน

  • มันเป็นเรื่องที่ไม่จำเป็นว่าถ้าวัตถุสองไม่เท่ากันตามequals(java.lang.Object)วิธีการแล้วเรียกhashCodeวิธีการในแต่ละวัตถุทั้งสองจะต้องก่อให้เกิดผลที่แตกต่างกันจำนวนเต็ม อย่างไรก็ตามโปรแกรมเมอร์ควรตระหนักว่าการสร้างผลลัพธ์จำนวนเต็มที่แตกต่างกันสำหรับวัตถุที่ไม่เท่ากันอาจปรับปรุงประสิทธิภาพของแฮชเทเบิลได้

เท่าที่เป็นจริงในทางปฏิบัติวิธีการ hashCode ที่กำหนดโดยวัตถุคลาสจะส่งกลับจำนวนเต็มที่แตกต่างกันสำหรับวัตถุที่แตกต่างกัน (โดยทั่วไปแล้วจะนำไปใช้โดยการแปลงที่อยู่ภายในของวัตถุให้เป็นจำนวนเต็มแต่ไม่จำเป็นต้องใช้เทคนิคการติดตั้งนี้ในภาษาการเขียนโปรแกรม Java)


14

ค่าที่ส่งคืนโดยhashCode()คือรหัสแฮชของวัตถุซึ่งเป็นที่อยู่หน่วยความจำของวัตถุเป็นเลขฐานสิบหก

ตามคำจำกัดความหากวัตถุสองชิ้นมีค่าเท่ากันรหัสแฮชจะต้องเท่ากัน หากคุณแทนที่equals()วิธีนี้คุณจะเปลี่ยนวิธีการจัดวางวัตถุสองรายการและการใช้งานวัตถุhashCode()ไม่ถูกต้องอีกต่อไป ดังนั้นหากคุณแทนที่เมธอด equals () คุณจะต้องแทนที่hashCode()เมธอดด้วยเช่นกัน

คำตอบนี้มาจากเอกสารการสอนอย่างเป็นทางการของ Java SE 8


13

hashCode()เป็นฟังก์ชั่นที่รับวัตถุและส่งออกค่าตัวเลข hashcode สำหรับวัตถุจะเหมือนกันเสมอหากวัตถุนั้นไม่เปลี่ยนแปลง

การทำงานเช่นHashMap, HashTable, HashSetฯลฯ ที่จำเป็นต้องเก็บวัตถุที่จะใช้hashCodeแบบโมดูโลขนาดของอาร์เรย์ภายในของพวกเขาที่จะเลือกในสิ่งที่ตำแหน่ง "ความทรงจำ" (คือตำแหน่งอาร์เรย์) ในการจัดเก็บวัตถุ

มีบางกรณีที่อาจเกิดการชน (วัตถุสองชิ้นลงท้ายด้วยแฮชโค้ดเดียวกัน) และแน่นอนว่าต้องแก้ไขอย่างระมัดระวัง


6

แม้ว่า hashcode จะไม่ทำอะไรกับตรรกะทางธุรกิจของคุณ แต่เราต้องดูแลในกรณีส่วนใหญ่ เนื่องจากเมื่อวัตถุของคุณใส่ลงในคอนเทนเนอร์ที่ใช้แฮช (HashSet, HashMap ... ) คอนเทนเนอร์จะใส่ / รับแฮชโค้ดขององค์ประกอบ


ไม่มันไม่ มันทำให้ / รับกุญแจ hashCode ใช้สำหรับการฝากเท่านั้น
Marquis of Lorne

3

แฮชโค้ดเป็นจำนวนที่สร้างจากวัตถุใด ๆ

นี่คือสิ่งที่ช่วยให้วัตถุสามารถจัดเก็บ / ดึงข้อมูลได้อย่างรวดเร็วใน Hashtable

ลองนึกภาพตัวอย่างง่ายๆต่อไปนี้:

บนโต๊ะข้างหน้าคุณ คุณมีเก้ากล่องแต่ละกล่องที่มีหมายเลข 1 ถึง 9 คุณมีกองวัตถุต่าง ๆ ที่เก็บไว้ในกล่องเหล่านี้ แต่เมื่อมีอยู่ในนั้นคุณจะต้องค้นหาให้เร็วที่สุด

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

ทีนี้ลองนึกภาพว่าคุณไม่ต้องการรบกวนดัชนีคุณต้องการค้นหาทันทีจากวัตถุที่อยู่ในกล่อง

ในตัวอย่างลองใช้วิธีง่ายๆในการทำสิ่งนี้ - จำนวนตัวอักษรในชื่อของวัตถุ ดังนั้นกะหล่ำปลีจะไปในกล่องที่ 7 ถั่วจะไปในกล่องที่ 3 จรวดในกล่องที่ 6 ที่แบนโจในกล่องที่ 5 และอื่น ๆ

แล้วแรดล่ะ? มันมี 10 ตัวอักษรดังนั้นเราจะเปลี่ยนอัลกอริทึมของเราเล็กน้อยและ "ล้อมรอบ" เพื่อให้วัตถุ 10 ตัวอักษรไปในกล่องที่ 1, 11 ตัวอักษรในกล่องที่ 2 เป็นต้น ที่ควรครอบคลุมวัตถุใด ๆ

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

นั่นคือรหัสแฮช วิธีรับหมายเลขจากวัตถุเพื่อให้สามารถเก็บไว้ใน Hashtable ใน Java รหัสแฮชสามารถเป็นจำนวนเต็มใด ๆ และวัตถุแต่ละชนิดมีหน้าที่สร้างของตัวเอง ค้นหาวิธี "hashCode" ของ Object

ที่มา - ที่นี่


-1

หนึ่งของการใช้งานของ hashCode () ที่จะสร้างกลไกการจับ ดูตัวอย่างนี้:

        class Point
    {
      public int x, y;

      public Point(int x, int y)
      {
        this.x = x;
        this.y = y;
      }

      @Override
      public boolean equals(Object o)
      {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Point point = (Point) o;

        if (x != point.x) return false;
        return y == point.y;
      }

      @Override
      public int hashCode()
      {
        int result = x;
        result = 31 * result + y;
        return result;
      }

class Line
{
  public Point start, end;

  public Line(Point start, Point end)
  {
    this.start = start;
    this.end = end;
  }

  @Override
  public boolean equals(Object o)
  {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    Line line = (Line) o;

    if (!start.equals(line.start)) return false;
    return end.equals(line.end);
  }

  @Override
  public int hashCode()
  {
    int result = start.hashCode();
    result = 31 * result + end.hashCode();
    return result;
  }
}
class LineToPointAdapter implements Iterable<Point>
{
  private static int count = 0;
  private static Map<Integer, List<Point>> cache = new HashMap<>();
  private int hash;

  public LineToPointAdapter(Line line)
  {
    hash = line.hashCode();
    if (cache.get(hash) != null) return; // we already have it

    System.out.println(
      String.format("%d: Generating points for line [%d,%d]-[%d,%d] (no caching)",
        ++count, line.start.x, line.start.y, line.end.x, line.end.y));
}

'การสร้างกลไกการจับ' หมายถึงอะไร และรหัสนี้แสดงให้เห็นได้อย่างไร
มาร์ควิสแห่ง Lorne

-1

hashCode()เป็นรหัสที่ไม่ซ้ำกันซึ่งสร้างโดย JVM สำหรับการสร้างวัตถุทุกครั้ง

เราใช้hashCode()เพื่อดำเนินการบางอย่างเกี่ยวกับอัลกอริทึมที่เกี่ยวข้องกับการแฮชเช่น Hashtable, Hashmap ฯลฯ

ข้อดีของการhashCode()ทำการค้นหาให้ง่ายเพราะเมื่อเราค้นหาวัตถุที่มีรหัสที่ไม่ซ้ำกันมันช่วยในการค้นหาวัตถุนั้น

แต่เราไม่สามารถพูดได้ว่าhashCode()เป็นที่อยู่ของวัตถุ มันเป็นรหัสที่ไม่ซ้ำกันที่สร้างขึ้นโดย JVM สำหรับทุกวัตถุ

นั่นคือเหตุผลที่อัลกอริทึมการแฮชปัจจุบันเป็นวิธีค้นหาที่นิยมมาก


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