[英]What is the use of hashCode in Java?
在 Java 中, obj.hashCode()
返回一些值。 這個哈希碼在編程中有什么用?
hashCode()
用於在HashMap
、 HashTable
、 HashSet
等Hash
實現中進行分桶。
從hashCode()
接收到的值用作存儲集合/映射元素的桶號。 這個桶號是集合/映射中元素的地址。
當您執行contains()
時,它將獲取元素的哈希碼,然后查找哈希碼指向的存儲桶。 如果在同一個bucket中發現超過1個元素(多個對象可以有相同的hash碼),那么它使用equals()
方法判斷對象是否相等,然后判斷contains()
是真還是假,或決定是否可以在集合中添加元素。
從Javadoc :
返回對象的哈希碼值。 支持這種方法是為了便於哈希表,例如
java.util.Hashtable
提供的哈希表。
hashCode
的一般合約是:
每當在 Java 應用程序執行期間對同一個對象多次調用它時,
hashCode
方法必須始終返回相同的 integer ,前提是沒有修改對象上的 equals 比較中使用的信息。 該整數不需要從應用程序的一次執行到同一應用程序的另一次執行保持一致。如果兩個對象根據
equals(Object)
方法相等,則對兩個對象中的每一個調用hashCode
方法必須產生相同的整數結果。如果根據
equals(java.lang.Object)
方法,如果兩個對象不相等,則不需要對兩個對象中的每一個調用hashCode
方法都必須產生不同的整數結果。 但是,程序員應該意識到,為不相等的對象生成不同的整數結果可能會提高哈希表的性能。在合理可行的情況下,由 Object 類定義的 hashCode 方法確實為不同的對象返回不同的整數。 (這通常通過將對象的內部地址轉換為整數來實現,但 Java 編程語言不需要這種實現技術。)
hashCode()
是一個接受對象並輸出數值的函數。 如果對象不變,則對象的哈希碼始終相同。
像HashMap
、 HashTable
、 HashSet
等需要存儲對象的函數將使用hashCode
對其內部數組的大小取模來選擇存儲對象的“內存位置”(即數組位置)。
在某些情況下可能會發生沖突(兩個對象最終具有相同的哈希碼),當然,這需要仔細解決。
hashCode()
返回的值是對象的哈希碼,即對象的十六進制內存地址。根據定義,如果兩個對象相等,則它們的哈希碼也必須相等。 如果重寫
equals()
方法,就會改變兩個對象相等的方式,並且 Object 的hashCode()
實現不再有效。 因此,如果你重寫 equals() 方法,你也必須重寫hashCode()
方法。
哈希碼是從任何對象生成的數字。
這就是允許在哈希表中快速存儲/檢索對象的原因。
想象一下以下簡單示例:
在你面前的桌子上。 你有九個盒子,每個盒子都標有數字 1 到 9。你還有一堆完全不同的物品要存放在這些盒子里,但是一旦它們在那里,你需要能夠盡快找到它們。
您需要的是一種立即決定將每個對象放入哪個盒子的方法。它就像一個索引。 你決定找到卷心菜,所以你查找卷心菜在哪個盒子里,然后直接去那個盒子拿。
現在假設您不想打擾索引,您希望能夠立即從對象中找出它所在的盒子。
在示例中,讓我們使用一種非常簡單的方法來執行此操作 - 對象名稱中的字母數。 所以卷心菜放在第 7 盒,豌豆放在第 3 盒,火箭放在第 6 盒,班卓琴放在第 5 盒,依此類推。
不過,犀牛呢? 它有 10 個字符,所以我們將稍微改變我們的算法並“環繞”,以便 10 個字母的對象進入框 1,11 個字母進入框 2,依此類推。 這應該涵蓋任何對象。
有時一個盒子里會有多個物品,但如果你在尋找火箭,比較花生和火箭仍然比檢查一整堆卷心菜、豌豆、班卓琴和犀牛要快得多。
那是一個哈希碼。 一種從對象中獲取數字以便將其存儲在哈希表中的方法。 在 Java 中,哈希碼可以是任何整數,並且每個對象類型負責生成自己的。 查找 Object 的“hashCode”方法。
來源 -這里
盡管哈希碼對您的業務邏輯沒有任何作用,但在大多數情況下我們必須處理它。 因為當您的對象被放入基於哈希的容器( HashSet
, HashMap
...)時,容器會放入/獲取元素的哈希碼。
哈希碼
每當您覆蓋 equals() 時,您也應該覆蓋 hashCode()。 將對象作為鍵存儲在映射中時使用哈希碼。
哈希碼是將類的實例放入有限數量的類別中的數字。 想象一下,我給了你一副牌,我告訴你我要問你特定的牌,我想盡快拿回正確的牌。 只要你想准備,你就可以准備,但是當我開始索要卡片時我很着急。 您可以制作 13 堆牌:所有 A 放在一堆,所有 2 放在另一堆,依此類推。 這樣,當我要求紅心五時,您可以從五張牌堆中的四張牌中拉出正確的牌。 這肯定比遍歷整副 52 張牌要快! 如果桌子上有足夠的空間,您甚至可以堆成 52 堆。
參考:OCP Oracle Certified Professional Java SE 8 Programmer II
hashCode()
是 JVM 為每個對象創建生成的唯一代碼。
我們使用hashCode()
對 Hashtable、Hashmap 等哈希相關算法執行一些操作。
hashCode()
的優點使搜索操作變得容易,因為當我們搜索具有唯一代碼的對象時,它有助於找出該對象。
但是我們不能說hashCode()
是一個對象的地址。 它是 JVM 為每個對象生成的唯一代碼。
這就是為什么現在散列算法是最流行的搜索算法。
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));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.