代码之家  ›  专栏  ›  技术社区  ›  cdmckay

我应该使用字符串字段的串联作为散列码吗?

  •  14
  • cdmckay  · 技术社区  · 15 年前

    我在C#中有一个Address类,看起来像这样:

    public class Address
    {            
        public string StreetAddress { get; set; }
        public string RuralRoute { get; set; }
        public string City { get; set; }
        public string Province { get; set; }
        public string Country { get; set; }
        public string PostalCode { get; set; }
    }
    

    即:

    var str = new StringBuilder();
    str.Append(StreetAddress)
       .Append(RuralRoute)
       ...
    
    return str.ToString().GetHashCode();
    

    这有什么优点/缺点?为什么我不应该这样做?

    4 回复  |  直到 15 年前
        1
  •  16
  •   Community Maksym Gontar    7 年前

    事实上

    我会选择我之前提到的“简单且容易找到正确的”算法 used in this answer (感谢您查找lance:)-正如您所说,它在有效Java中列出。在这种情况下,其结果将是:

    public int GetHashCode()
    {
        int hash = 17;
        // Suitable nullity checks etc, of course :)
        hash = hash * 23 + StreetAddress.GetHashCode();
        hash = hash * 23 + RuralRoute.GetHashCode();
        hash = hash * 23 + City.GetHashCode();
        hash = hash * 23 + Province.GetHashCode();
        hash = hash * 23 + Country.GetHashCode();
        hash = hash * 23 + PostalCode.GetHashCode();
        return hash;
    }
    

    当然,这不是零安全的。如果您使用的是C 3,那么您可能需要考虑一种扩展方法:

    public static int GetNullSafeHashCode<T>(this T value) where T : class
    {
        return value == null ? 1 : value.GetHashCode();
    }
    

    public int GetHashCode()
    {
        int hash = 17;
        // Suitable nullity checks etc, of course :)
        hash = hash * 23 + StreetAddress.GetNullSafeHashCode();
        hash = hash * 23 + RuralRoute.GetNullSafeHashCode();
        hash = hash * 23 + City.GetNullSafeHashCode();
        hash = hash * 23 + Province.GetNullSafeHashCode();
        hash = hash * 23 + Country.GetNullSafeHashCode();
        hash = hash * 23 + PostalCode.GetNullSafeHashCode();
        return hash;
    }
    

    能够

    public static int GetHashCode(params object[] values)
    {
        int hash = 17;
        foreach (object value in values)
        {
            hash = hash * 23 + value.GetNullSafeHashCode();
        }
        return hash;
    }
    

    public int GetHashCode()
    {
        return HashHelpers.GetHashCode(StreetAddress, RuralRoute, City,
                                       Province, Country, PostalCode);
    }
    

    在大多数类型中,都会涉及到原语,因此执行装箱操作有些不必要,但在这种情况下,您只能使用引用。当然,你最终会不必要地创建一个数组,但是你知道他们怎么说过早优化。。。

        2
  •  5
  •   Kosi2801    15 年前

    想想

    "StreetAddress" + "RuralRoute" + "City"
    

    "Street" + "AddressRural" + "RouteCity"
    

    两者的哈希代码相同,但字段中的内容不同。

        3
  •  0
  •   Keltex    15 年前

    IEqualityComparer<Address> :

    public class Address : IEqualityComparer<Address>
    {        
        //
        // member declarations
        //
    
        bool IEqualityComparer<Address>.Equals(Address x, Address y)
        {
            // implementation here
        }
    
        int IEqualityComparer<Address>.GetHashCode(Item obj)
        {
            // implementation here
        }
    }
    

    您还可以实现 IComparable<Address> 要获得订单。。。

        4
  •  -4
  •   Wouter Asim    9 年前
    public string getfourDigitEncryptedText(string input) { 
        int hashCode = input.hashCode(); 
        string hstring = (new StringBuilder()).append(hashCode).append("").toString(); 
        string rev_hstring = (new StringBuilder(hstring)).reverse().toString(); 
        string parts[] = rev_hstring.trim().split(""); 
        int prefixint = 0; 
        for(int i = 1; i <= parts.length - 3; i++) 
            prefixint += integer.parseInt(parts[i]);   
        string prefixstr = "0"; 
        if((new integer(prefixint)).toString().length() < 2) 
            prefixstr = (new StringBuilder()).append((new integer(prefixint)).toString()).append("5").toString(); 
        else if((new integer(prefixint)).toString().length() > 2) 
            prefixstr = "79"; 
        else 
            prefixstr = (new integer(prefixint)).toString(); 
        string finalstr = (new StringBuilder()).append(prefixint).append(rev_hstring.substring(3, 5)).toString();
        return finalstr; 
    }