CodeGym /Blog Java /Ngẫu nhiên /Mã băm Java()

Mã băm Java()

Xuất bản trong nhóm

Nguyên tắc băm

Trước hết, trước khi định nghĩa mã băm Java, chúng ta cần hiểu băm là gì và dùng để làm gì. Băm là một quá trình áp dụng hàm băm cho một số dữ liệu. Hàm băm chỉ là một hàm toán học. Đừng lo lắng về điều này! “Toán học” không phải lúc nào cũng có nghĩa là “phức tạp”. Ở đây, điều đó chỉ có nghĩa là chúng ta có một số dữ liệu và một quy tắc nhất định ánh xạ dữ liệu thành một bộ ký tự (mã). Ví dụ, nó có thể là một mật mã thập lục phân. Chúng tôi có một số dữ liệu ở bất kỳ kích thước nào ở đầu vào và áp dụng hàm băm cho dữ liệu đó. Ở đầu ra, chúng tôi nhận được dữ liệu có kích thước cố định, chẳng hạn như 32 ký tự. Thông thường, loại hàm đó sẽ chuyển đổi một phần dữ liệu lớn thành một giá trị số nguyên nhỏ. Kết quả của công việc chức năng này được gọi là mã băm. Các hàm băm được sử dụng rộng rãi trong mật mã học và một số lĩnh vực khác nữa. Các hàm băm có thể khác nhau,
  • Một đối tượng cụ thể có một mã băm cụ thể.
  • Nếu hai đối tượng bằng nhau, mã băm của chúng giống nhau. Điều ngược lại là không đúng sự thật.
  • Nếu các mã băm khác nhau, thì chắc chắn các đối tượng không bằng nhau.
  • Các đối tượng khác nhau có thể có cùng mã băm. Tuy nhiên, đó là một sự kiện rất khó xảy ra. Tại thời điểm này, chúng tôi có một vụ va chạm, một tình huống mà chúng tôi có thể mất dữ liệu.
Hàm băm "thích hợp" giảm thiểu xác suất va chạm.

Mã băm trong Java

Trong hàm băm Java thường được kết nối với phương thức hashCode() . Chính xác, kết quả của việc áp dụng hàm băm cho Đối tượng là mã băm. Mọi đối tượng Java đều có mã băm. Nói chung Hash Code là một số được tính bằng phương thức hashCode() của Objectlớp. Thông thường, các lập trình viên ghi đè phương thức này cho các đối tượng của họ cũng như liên quan đến hashCode() phương thức equals() để xử lý dữ liệu cụ thể hiệu quả hơn. Phương thức hashCode () trả về một giá trị int (4 byte), là một biểu diễn số của đối tượng. Ví dụ, mã băm này được sử dụng bởi các bộ sưu tập để lưu trữ dữ liệu hiệu quả hơn và theo đó, truy cập chúng nhanh hơn. Theo mặc định, hashCode()hàm cho một đối tượng trả về số ô nhớ nơi đối tượng được lưu trữ. Do đó, nếu không có thay đổi nào được thực hiện đối với mã ứng dụng thì hàm sẽ trả về cùng một giá trị. Nếu mã thay đổi một chút, giá trị mã băm cũng thay đổi. Mã băm được sử dụng trong Java là gì? Trước hết, mã băm Java giúp chương trình chạy nhanh hơn. Ví dụ: nếu chúng ta so sánh hai đối tượng o1o2thuộc một loại nào đó, thao tác o1.equals(o2)sẽ mất thời gian gấp khoảng 20 lần so với o1.hashCode() == o2.hashCode().

Java bằng()

Trong lớp cha Object, cùng với phương thức hashCode() , còn có equals() , hàm dùng để kiểm tra sự bằng nhau của hai đối tượng. Việc triển khai mặc định của chức năng này chỉ đơn giản là kiểm tra các liên kết của hai đối tượng xem chúng có tương đương không. equals()hashCode() có hợp đồng của chúng, vì vậy nếu bạn ghi đè một trong số chúng, bạn nên ghi đè cái kia để không phá vỡ hợp đồng này.

Triển khai phương thức hashCode()

Ví dụ

Hãy tạo một lớp Character với một trường — name . Sau đó, chúng ta tạo hai đối tượng thuộc lớp Character là character1character2 và đặt tên cho chúng giống nhau. Nếu chúng ta sử dụng hashCode()equals() mặc định của lớp Object , chắc chắn chúng ta sẽ nhận được các đối tượng khác nhau, không bằng nhau. Đó là cách mã băm trong Java hoạt động. Chúng sẽ có các mã băm khác nhau vì chúng nằm trong các ô nhớ khác nhau và kết quả phép toán bằng() sẽ sai.

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));
    }
}
Kết quả chạy chương trình:

Arnold
1595428806
Arnold
1072408673
false
Hai số có 10 chữ số trong bảng điều khiển là mã băm. Nếu chúng ta muốn có các đối tượng bằng nhau nếu chúng có cùng tên thì sao? Chúng ta nên làm gì? Câu trả lời: chúng ta nên ghi đè các phương thức hashCode()equals() của lớp Object cho lớp Character của chúng ta . Chúng tôi có thể làm điều đó tự động trong IDEA IDE, chỉ cần nhấn alt + insert trên bàn phím của bạn và chọn Generate -> equals() và hashCode() . Java hashCode() - 2 là gìTrong trường hợp ví dụ của chúng tôi, chúng tôi có mã tiếp theo:

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));
    }
}
Kết quả của việc chạy mã này:

Arnold
1969563338
Arnold
1969563338
true
Vì vậy, bây giờ chương trình xác định các đối tượng của chúng ta bằng nhau và chúng có cùng mã băm.

Ví dụ mã băm Java:

hashCode() và equals() của riêng bạn

Bạn cũng có thể tạo các hiện thực equals()hashCode() của riêng mình , nhưng hãy cẩn thận và nhớ giảm thiểu xung đột mã băm. Đây là một ví dụ về các phương thức hashCode()equals() của chúng ta trong lớp 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));
   }
}
Và lớp Chính để chứng minh công việc của họ:

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));
   }
}

Mã băm được sử dụng để làm gì?

Trước hết, mã băm giúp chương trình chạy nhanh hơn. Ví dụ: nếu chúng ta so sánh hai đối tượng o1o2thuộc một loại nào đó, thao tác o1.equals(o2)sẽ mất thời gian gấp khoảng 20 lần so với o1.hashCode() == o2.hashCode(). Trong nguyên tắc băm Java đứng đằng sau một số bộ sưu tập phổ biến, chẳng hạn như HashMap , HashSetHashTable .

Phần kết luận

Mọi đối tượng Java đều có các phương thức hashCode()equals() kế thừa từ lớp Object . Để có một cơ chế bình đẳng hoạt động tốt, tốt hơn bạn nên ghi đè các phương thức hashcode()equals() cho các lớp của riêng bạn. Sử dụng mã băm giúp chương trình chạy nhanh hơn.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION