John Squirrels
ระดับ
San Francisco

Java hashCode()

เผยแพร่ในกลุ่ม

หลักการแฮช

ก่อนอื่น ก่อนที่เราจะกำหนดรหัสแฮชของ Java เราต้องเข้าใจว่าการแฮชคืออะไรและมีไว้เพื่ออะไร การแฮชเป็นกระบวนการของการใช้ฟังก์ชันแฮชกับข้อมูลบางอย่าง ฟังก์ชันแฮชเป็นเพียงฟังก์ชันทางคณิตศาสตร์ ไม่ต้องกังวลกับเรื่องนี้! “คณิตศาสตร์” ไม่ได้หมายความว่า “ซับซ้อน” เสมอไป ในที่นี้หมายความว่าเรามีข้อมูลบางส่วนและกฎบางอย่างที่แมปข้อมูลเป็นชุดอักขระ (รหัส) ตัวอย่างเช่น อาจเป็นรหัสตัวเลขฐานสิบหก เรามีข้อมูลขนาดใดก็ได้ที่อินพุต และใช้ฟังก์ชันแฮชกับข้อมูลนั้น ที่เอาต์พุต เราได้รับข้อมูลขนาดคงที่ เช่น 32 ตัวอักษร โดยปกติแล้ว ฟังก์ชันประเภทนี้จะแปลงข้อมูลขนาดใหญ่ให้เป็นค่าจำนวนเต็มขนาดเล็ก ผลลัพธ์ของการทำงานของฟังก์ชันนี้เรียกว่ารหัสแฮช ฟังก์ชันแฮชถูกใช้อย่างแพร่หลายในการเข้ารหัส และบางพื้นที่ด้วยเช่นกัน ฟังก์ชันแฮชอาจแตกต่างกัน
  • วัตถุเฉพาะมีรหัสแฮชเฉพาะ
  • หากวัตถุสองชิ้นมีค่าเท่ากัน รหัสแฮชของวัตถุทั้งสองจะเหมือนกัน สิ่งที่ตรงกันข้ามไม่เป็นความจริง
  • หากรหัสแฮชต่างกันแสดงว่าวัตถุนั้นไม่เท่ากันอย่างแน่นอน
  • วัตถุที่แตกต่างกันอาจมีรหัสแฮชเดียวกัน อย่างไรก็ตาม มันเป็นเหตุการณ์ที่ไม่น่าเกิดขึ้นมากนัก ณ จุดนี้ เรามีการปะทะกัน สถานการณ์ที่เราอาจสูญเสียข้อมูล
ฟังก์ชันแฮชที่ "เหมาะสม" ช่วยลดความน่าจะเป็นของการชนกันให้เหลือน้อยที่สุด

แฮชโค้ดในภาษาจาวา

ในฟังก์ชันแฮช Java มักจะเชื่อมต่อกับเมธอด hashCode( ) ผลลัพธ์ของการใช้ฟังก์ชันแฮชกับอ็อบเจกต์คือแฮชโค้ด ทุกวัตถุ Java มีรหัสแฮช โดยทั่วไป Hash Code คือตัวเลขที่คำนวณโดยhashCode() วิธีการของObjectคลาส โดยปกติแล้ว โปรแกรมเมอร์จะแทนที่เมธอดนี้สำหรับออบเจกต์ของตน เช่นเดียวกับ เมธอด hashCode() the equals()เพื่อการประมวลผลข้อมูลเฉพาะอย่างมีประสิทธิภาพมากขึ้น เมธอดhashCode()ส่งคืนค่า int (4 ไบต์) ซึ่งเป็นการแสดงตัวเลขของวัตถุ ตัวอย่างเช่น แฮชโค้ดนี้ถูกใช้โดยคอลเล็กชันเพื่อการจัดเก็บข้อมูลที่มีประสิทธิภาพมากขึ้น และด้วยเหตุนี้ การเข้าถึงจึงเร็วขึ้น โดยค่าเริ่มต้นhashCode()ฟังก์ชันสำหรับออบเจกต์จะส่งคืนจำนวนเซลล์หน่วยความจำที่เก็บออบเจ็กต์ไว้ ดังนั้นหากไม่มีการเปลี่ยนแปลงรหัสแอปพลิเคชัน ฟังก์ชันควรคืนค่าเดิม หากโค้ดเปลี่ยนแปลงเล็กน้อย ค่าแฮชโค้ดก็จะเปลี่ยนไปด้วย แฮชโค้ดที่ใช้ใน Java คืออะไร ประการแรก แฮชโค้ด Java ช่วยให้โปรแกรมทำงานได้เร็วขึ้น ตัวอย่างเช่น หากเราเปรียบเทียบวัตถุสองชิ้นo1กับวัตถุ o2บางประเภท การดำเนินการo1.equals(o2)จะใช้เวลามากกว่า 20 เท่าo1.hashCode() == o2.hashCode()

Java เท่ากับ ()

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

การใช้ hashCode() วิธีการ

ตัวอย่าง

มาสร้างคลาสCharacter ด้วยฟิลด์เดียว — ชื่อ หลังจากนั้น เราสร้างอ็อบเจกต์ คลาส Character สอง รายการcharacter1และcharacter2และตั้งชื่อให้เหมือนกัน หากเราใช้ค่าเริ่มต้นhashCode()และเท่ากับ()ของ คลาส Objectเราจะได้วัตถุที่แตกต่างกันและไม่เท่ากัน นั่นคือวิธีการทำงานของ hashcode ใน Java พวกเขาจะมีรหัสแฮชที่แตกต่างกันเนื่องจากอยู่ในเซลล์หน่วยความจำที่แตกต่างกันและ ผลลัพธ์ของการดำเนินการ เท่ากับ ()จะเป็นเท็จ

import java.util.Objects;

public class Character {
    private String Name;

    public Character(String name) {
        Name = name;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    } 

    public static void main(String[] args) {
        Character character1 = new Character("Arnold");
        System.out.println(character1.getName());
        System.out.println(character1.hashCode());
        Character character2 = new Character("Arnold");
        System.out.println(character2.getName());
        System.out.println(character2.hashCode());
        System.out.println(character2.equals(character1));
    }
}
ผลลัพธ์ของการเรียกใช้โปรแกรม:

Arnold
1595428806
Arnold
1072408673
false
ตัวเลข 10 หลักสองตัวในคอนโซลคือรหัสแฮช จะทำอย่างไรถ้าเราต้องการให้วัตถุเท่ากันหากมีชื่อเหมือนกัน เราควรทำอย่างไร? คำตอบ: เราควรแทนที่เมธอด hashCode()และequals()ของ คลาส ObjectสำหรับคลาสCharacter ของเรา เราสามารถทำได้โดยอัตโนมัติใน IDEA IDE เพียงกดalt + insertบนแป้นพิมพ์ของคุณแล้วเลือกGenerate -> equals() และ hashCode( ) Java hashCode() คืออะไร - 2ในกรณีตัวอย่างของเรา เรามีโค้ดถัดไป:

import java.util.Objects;

public class Character {
    private String Name;

    public Character(String name) {
        Name = name;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Character)) return false;

        Character character = (Character) o;

        return getName() != null ? getName().equals(character.getName()) : character.getName() == null;
    }

    @Override
    public int hashCode() {
        return getName() != null ? getName().hashCode() : 0;
    }

    public static void main(String[] args) {
        Character character1 = new Character("Arnold");
        System.out.println(character1.getName());
        System.out.println(character1.hashCode());
        Character character2 = new Character("Arnold");
        System.out.println(character2.getName());
        System.out.println(character2.hashCode());
        System.out.println(character2.equals(character1));
    }
}
ผลลัพธ์ของการเรียกใช้รหัสนี้:

Arnold
1969563338
Arnold
1969563338
true
ตอนนี้โปรแกรมระบุว่าวัตถุของเราเท่ากันและมีรหัสแฮชเหมือนกัน

ตัวอย่างแฮชโค้ด Java:

hashCode ของคุณเอง () และเท่ากับ ()

คุณยังสามารถสร้างการสำนึก เท่ากับ ()และhashCode ()ของคุณเองแต่โปรดระวังและอย่าลืมลดการชนกันของรหัสแฮช นี่คือตัวอย่างเมธอด hashCode()และequals() ของเราเอง ใน คลาส Student :

import java.util.Date;

public class Student {
   String surname;
   String name;
   String secondName;
   Long birthday; // Long instead of long is used by Gson/Jackson json parsers and various orm databases

   public Student(String surname, String name, String secondName, Date birthday ){
       this.surname = surname;
       this.name = name;
       this.secondName = secondName;
       this.birthday = birthday == null ? 0 : birthday.getTime();
   }
//Java hashcode example
   @Override
   public int hashCode(){
       //TODO: check for nulls
       //return surname.hashCode() ^ name.hashCode() ^ secondName.hashCode() ^ (birthday.hashCode());
       return (surname + name + secondName + birthday).hashCode();
   }
   @Override
   public boolean equals(Object other_) {
       Student other = (Student)other_;
       return (surname == null || surname.equals(other.surname) )
               && (name == null || name.equals(other.name))
               && (secondName == null || secondName.equals(other.secondName))
               && (birthday == null || birthday.equals(other.birthday));
   }
}
และ ชั้นเรียน หลักเพื่อสาธิตการทำงานของพวกเขา:

import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;

public class Main {
   static HashMap<Student, Integer> cache = new HashMap<Student, Integer>(); // <person, targetPriority>

   public static void main(String[] args) {
       Student sarah1 = new Student("Sarah","Connor", "Jane", null);
       Student sarah2 = new Student("Sarah","Connor", "Jane", new Date(1970, 01-1, 01));
       Student sarah3 = new Student("Sarah","Connor", "Jane", new Date(1959, 02-1, 28)); // date not exists
       Student john = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
       Student johnny = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
       System.out.println(john.hashCode());
       System.out.println(johnny.hashCode());
       System.out.println(sarah1.hashCode());
       System.out.println();
       cache.put(sarah1, 1);
       cache.put(sarah2, 2);
       cache.put(sarah3, 3);
       System.out.println(new Date(sarah1.birthday));
       System.out.println();
       cache.put(john, 5);
       System.out.println(cache.get(john));
       System.out.println(cache.get(johnny));
       cache.put(johnny, 7);
       System.out.println(cache.get(john));
       System.out.println(cache.get(johnny));
   }
}

แฮชโค้ดใช้สำหรับอะไร

ประการแรก แฮชโค้ดช่วยให้โปรแกรมทำงานได้เร็วขึ้น ตัวอย่างเช่น หากเราเปรียบเทียบวัตถุสองชิ้นo1และo2บางประเภท การดำเนินการo1.equals(o2)จะใช้เวลามากกว่า o1.hashCode() == o2.hashCode() ประมาณ 20 เท่า ในหลักการแฮชของ Java นั้นอยู่เบื้องหลังคอลเล็กชันยอด นิยม เช่นHashMap , HashSetและHashTable

บทสรุป

วัตถุ Java ทุกตัวมีเมธอด hashCode()และเท่ากับ()ที่สืบทอดมาจากคลาสอ็อบเจกต์ เพื่อให้ได้กลไกความเท่าเทียมกันที่ใช้งานได้ดี คุณควรแทนที่เมธอดhashcode()และequals()สำหรับคลาสของคุณเอง การใช้แฮชโค้ดทำให้โปรแกรมทำงานเร็วขึ้น
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION