簡體   English   中英

如何測試哈希函數?

[英]How to test a hash function?

有沒有辦法測試哈希函數的質量? 我想在哈希表中使用時有一個很好的傳播,如果在單元測試中可以驗證它會很好。

編輯 :為了澄清,我的問題是我在Java中使用了long值,使得前32位編碼ID,第二位32位編碼另一個ID。 不幸的是,Java的長值散列只是將前32位與第二位32位異或,這在我的情況下導致在HashMap使用時性能非常差。 所以我需要一個不同的哈希,並希望有一個單元測試,以便這個問題不再蔓延。

首先,我認為你必須通過對自己的良好傳播來定義你的意思。 您是指對所有可能的輸入進行良好的傳播,還是僅為可能的輸入提供良好的傳播?

例如,如果您正在散列表示正確的完整(第一個+最后一個)名稱的字符串,那么您可能不會關心使用數字ASCII字符散列的內容。

至於測試,你最好的選擇是獲得你期望的大量或隨機輸入數據集,並通過哈希函數推送它,看看傳播是如何結束的。 可能不會有一個魔術程序可以說“是的,這對你的用例來說是一個很好的哈希函數。” 但是,如果您可以以編程方式生成輸入數據,則應該可以輕松地創建生成大量數據的單元測試,然后驗證擴展是否在您的定義中。

編輯:在64位長的情況下,是否真的有理由使用哈希映射? 為什么不直接使用平衡樹,直接使用long作為密鑰而不是重新使用它? 您在整體節點大小(鍵值大小的2倍)上支付一點點罰款,但最終可能會將其保存在性能上。

您必須使用從您期望它處理的相同(或類似)分發中提取的數據來測試您的哈希函數。 當查看64位長的散列函數時,如果從所有可能的長值統一繪制輸入值,則默認的Java散列函數非常好。

但是,您已經提到應用程序使用long來存儲基本上兩個獨立的32位值。 嘗試生成一個類似於您期望實際使用的值的樣本,然后使用它進行測試。

對於測試本身,獲取樣本輸入值,對每個值進行散列並將結果放入集合中。 計算結果集的大小,並將其與輸入集的大小進行比較,這將告訴您哈希函數生成的沖突數。

對於您的特定應用程序,不要簡單地將它們一起進行異或,而是嘗試將32位值組合在一起,典型的良好散列函數將組合兩個獨立的int。 即乘以素數,然后加上。

如果您使用鏈式哈希表,那么您真正關心的是沖突的數量。 在哈希表上作為一個簡單的計數器實現這將是微不足道的。 每次插入一個項目並且表格必須鏈接時,遞增鏈式計數器。 更好的散列算法將導致更少的沖突。 一個好的通用表哈希函數檢查是: djb2

根據您的澄清:

我在Java中使用了long值,使得前32位編碼ID,第二位32位編碼另一ID。 不幸的是,Java的長值散列只是將前32位與第二位32位異或,這在我的情況下導致在HashMap中使用時性能非常差。

看來你在分配兩個ID值的方式和HashMap實例的大小之間存在一些不愉快的“共振”。

您是明確調整地圖大小,還是使用默認值? QAD檢查似乎表明HashMap<Long,String>以16桶結構開始,並在溢出時加倍。 這意味着只有ID值的低位實際上參與了散列桶選擇。 您可以嘗試使用其中一個采用初始大小參數的構造函數,並使用初始大小創建地圖。

或者,Dave L'建議定義自己的長鍵散列將允許您避免低位依賴性問題。

另一種看待這種情況的方法是你使用原始類型(long)作為避免定義真實類的方法。 我建議通過定義業務類,然后在您自己的類上實現哈希編碼,相等和其他方法來管理此問題來查看可以實現的好處。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM