CodeGym /Java Blog /Toto sisi /Java 哈希碼()
John Squirrels
等級 41
San Francisco

Java 哈希碼()

在 Toto sisi 群組發布

哈希原理

首先,在我們定義Java哈希碼之前,我們需要了解什麼是哈希以及它有什麼用。哈希是將哈希函數應用於某些數據的過程。哈希函數只是一個數學函數。別擔心這個!“數學”並不總是意味著“複雜”。這裡只表示我們有一些數據和將數據映射成一組字符(代碼)的某種規則。例如,它可以是十六進制密碼。我們在輸入端有一些任意大小的數據,並對其應用哈希函數。在輸出中,我們得到一個固定大小的數據,比如 32 個字符。通常,這種函數將一大段數據轉換成一個小的整數值。該函數工作的結果稱為哈希碼。哈希函數廣泛用於密碼學和其他一些領域。哈希函數可以不同,
  • 特定對象具有特定的哈希碼。
  • 如果兩個對象相等,則它們的哈希碼相同。反之則不然。
  • 如果哈希碼不同,則對象肯定不相等。
  • 不同的對象可能具有相同的哈希碼。然而,這是一個極不可能發生的事件。在這一點上,我們有一個碰撞,一個我們可能會丟失數據的情況。
“適當的”散列函數將衝突的可能性降到最低。

Java 中的哈希碼

在 Java 中,哈希函數通常連接到hashCode() 方法。準確地說,將哈希函數應用於對象的結果是哈希碼。每個 Java 對像都有一個哈希碼。一般來說,Hash Code 是通過類的hashCode() 方法計算出來的一個數字Object。通常,程序員會為他們的對象重寫此方法以及與hashCode()相關的equals ()方法,以便更有效地處理特定數據。hashCode ()方法返回一個 int(4 字節)值,它是對象的數字表示。例如,集合使用此哈希碼來更有效地存儲數據,並相應地更快地訪問它們。默認情況下,hashCode()對象的函數返回存儲對象的內存單元的編號。因此,如果不對應用程序代碼進行更改,則該函數應返回相同的值。如果代碼稍有變化,哈希碼值也會發生變化。Java中使用的哈希碼是什麼?首先,Java 哈希碼幫助程序運行得更快。例如,如果我們比較兩個對象o1o2某種類型,該操作o1.equals(o2)所花費的時間大約是 的 20 倍o1.hashCode() == o2.hashCode()

Java 等於()

在父類中Object,除了hashCode()方法之外,還有equals(),用於檢查兩個對像是否相等的函數。此函數的默認實現只是檢查兩個對象的鏈接是否等價。 equals()hashCode()有它們的契約,所以如果你覆蓋其中一個,你應該覆蓋另一個,以免破壞這個契約。

實現 hashCode() 方法

例子

讓我們用一個字段創建一個類Character — name。之後,我們創建兩個Character類的對象character1character2並設置它們相同的名稱。如果我們使用Object類的默認hashCode()equals(),我們肯定會得到不同的,而不是相等的對象。Java 中的 hashcode 就是這樣工作的。它們將具有不同的哈希碼,因為它們位於不同的內存單元中,並且equals()操作結果將為 false。

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 位數字是哈希碼。如果我們想要擁有相同名稱的相同對象怎麼辦?我們應該做什麼?答案:我們應該為我們的Character類覆蓋Object類的hashCode()equals()方法。我們可以在 IDEA IDE 中自動完成,只需按鍵盤上的alt + insert並選擇Generate -> equals() and 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() 和 equals()

您也可以創建自己的equals()hashCode()實現,但要小心並記住盡量減少哈希碼衝突。這是我們在Student類中自己的hashCode()equals()方法的示例:

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

哈希碼有什麼用?

首先,哈希碼幫助程序運行得更快。例如,如果我們比較兩個對象o1o2某種類型,該操作o1.equals(o2)比 o1.hashCode() == o2.hashCode() 花費大約 20 倍的時間。在 Java 中,散列原理支持一些流行的集合,例如HashMapHashSetHashTable

結論

每個 Java 對像都有繼承自Object類的hashCode()equals()方法。要獲得良好的工作平等機制,您最好為您自己的類覆蓋hashcode()equals()方法。使用哈希碼可以使程序運行得更快。
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION