第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

重寫System.Object.GetHashCode的最佳算法是什么?

重寫System.Object.GetHashCode的最佳算法是什么?

米琪卡哇伊 2019-05-22 14:40:36
重寫System.Object.GetHashCode的最佳算法是什么?在.NET System.Object.GetHashCode方法中,很多地方都使用.NET 方法。特別是在快速查找集合中的項目或確定相等性時。是否有關于如何GetHashCode為我的自定義類實現(xiàn)覆蓋的標準算法/最佳實踐,因此我不會降低性能?
查看完整描述

4 回答

?
白板的微信

TA貢獻1883條經驗 獲得超3個贊

我通常會使用Josh Bloch 精彩的 Effective Java中的實現(xiàn)。它很快并且創(chuàng)建了一個非常好的哈希,不太可能導致沖突。選擇兩個不同的素數(shù),例如17和23,并執(zhí)行:

public override int GetHashCode(){
    unchecked // Overflow is fine, just wrap
    {
        int hash = 17;
        // Suitable nullity checks etc, of course :)
        hash = hash * 23 + field1.GetHashCode();
        hash = hash * 23 + field2.GetHashCode();
        hash = hash * 23 + field3.GetHashCode();
        return hash;
    }}

正如評論中所指出的,你可能會發(fā)現(xiàn)最好選擇一個大素數(shù)乘以。顯然486187739是好的...雖然我看到的大多數(shù)例子都是小數(shù)字傾向于使用素數(shù),但至少有類似的算法,其中經常使用非素數(shù)。例如,在后來的非FNV例子中,我使用的數(shù)字顯然效果很好 - 但初始值不是素數(shù)。(乘法常數(shù)雖然素數(shù)。我不知道它有多重要。)

這比XOR出于哈希碼的常見做法更好,主要有兩個原因。假設我們有一個包含兩個int字段的類型:

XorHash(x, x) == XorHash(y, y) == 0 for all x, yXorHash(x, y) == XorHash(y, x) for all x, y

順便說一下,早期的算法是C#編譯器當前用于匿名類型的算法。

這個頁面提供了很多選擇。我認為在大多數(shù)情況下,上述情況“足夠好”并且非常容易記住并且正確。所述FNV替代方案是同樣簡單,但使用不同的常數(shù)和XOR代替ADD作為組合操作。它看起來的東西像下面的代碼,但正常的FNV算法對每個字節(jié)進行操作,所以這將需要修改來執(zhí)行的,而不是每32位的哈希值每字節(jié)一個迭代。FNV也是為可變長度的數(shù)據(jù)而設計的,而我們在這里使用它的方式總是針對相同數(shù)量的字段值。對這個答案的評論表明,這里的代碼實際上并不像上面的添加方法那樣(在測試的示例中)。

// Note: Not quite FNV!public override int GetHashCode(){
    unchecked // Overflow is fine, just wrap
    {
        int hash = (int) 2166136261;
        // Suitable nullity checks etc, of course :)
        hash = (hash * 16777619) ^ field1.GetHashCode();
        hash = (hash * 16777619) ^ field2.GetHashCode();
        hash = (hash * 16777619) ^ field3.GetHashCode();
        return hash;
    }}

請注意,有一點需要注意的是,理想情況下,在將其添加到依賴于哈希代碼的集合之后,應該防止對等式敏感(因此對哈希碼敏感)狀態(tài)的更改。

根據(jù)文件

您可以為不可變引用類型重寫GetHashCode。通常,對于可變引用類型,只有在以下情況下才應覆蓋GetHashCode:

  • 您可以從不可變的字段計算哈希碼; 要么

  • 您可以確保在對象包含在依賴于其哈希代碼的集合中時,可變對象的哈希碼不會更改。


查看完整回答
反對 回復 2019-05-22
?
飲歌長嘯

TA貢獻1951條經驗 獲得超3個贊

這是我的哈希碼助手。
它的優(yōu)點是它使用泛型類型參數(shù),因此不會導致裝箱:

public static class HashHelper{
    public static int GetHashCode<T1, T2>(T1 arg1, T2 arg2)
    {
         unchecked
         {
             return 31 * arg1.GetHashCode() + arg2.GetHashCode();
         }
    }

    public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
    {
        unchecked
        {
            int hash = arg1.GetHashCode();
            hash = 31 * hash + arg2.GetHashCode();
            return 31 * hash + arg3.GetHashCode();
        }
    }

    public static int GetHashCode<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, 
        T4 arg4)
    {
        unchecked
        {
            int hash = arg1.GetHashCode();
            hash = 31 * hash + arg2.GetHashCode();
            hash = 31 * hash + arg3.GetHashCode();
            return 31 * hash + arg4.GetHashCode();
        }
    }

    public static int GetHashCode<T>(T[] list)
    {
        unchecked
        {
            int hash = 0;
            foreach (var item in list)
            {
                hash = 31 * hash + item.GetHashCode();
            }
            return hash;
        }
    }

    public static int GetHashCode<T>(IEnumerable<T> list)
    {
        unchecked
        {
            int hash = 0;
            foreach (var item in list)
            {
                hash = 31 * hash + item.GetHashCode();
            }
            return hash;
        }
    }

    /// <summary>
    /// Gets a hashcode for a collection for that the order of items 
    /// does not matter.
    /// So {1, 2, 3} and {3, 2, 1} will get same hash code.
    /// </summary>
    public static int GetHashCodeForOrderNoMatterCollection<T>(
        IEnumerable<T> list)
    {
        unchecked
        {
            int hash = 0;
            int count = 0;
            foreach (var item in list)
            {
                hash += item.GetHashCode();
                count++;
            }
            return 31 * hash + count.GetHashCode();
        }
    }

    /// <summary>
    /// Alternative way to get a hashcode is to use a fluent 
    /// interface like this:<br />
    /// return 0.CombineHashCode(field1).CombineHashCode(field2).
    ///     CombineHashCode(field3);
    /// </summary>
    public static int CombineHashCode<T>(this int hashCode, T arg)
    {
        unchecked
        {
            return 31 * hashCode + arg.GetHashCode();   
        }
    }

它還有擴展方法來提供流暢的界面,所以你可以像這樣使用它:

public override int GetHashCode(){
    return HashHelper.GetHashCode(Manufacturer, PartN, Quantity);}

或者像這樣:

public override int GetHashCode(){
    return 0.CombineHashCode(Manufacturer)
        .CombineHashCode(PartN)
        .CombineHashCode(Quantity);}


查看完整回答
反對 回復 2019-05-22
  • 4 回答
  • 0 關注
  • 877 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網(wǎng)微信公眾號