none
关于不同Guid取哈希值雷同的问题 RRS feed

  • 问题

  • 因为某个项目里面要求只能使用long类型的值作为主键,所以我就用Guid.NewGuid().ToHashCode想生成一个不重复的整数值,
    结果发现根本不行,如下所示,产生了重复值,为何Guid不同,哈希值会相同呢?不理解,请会的帮忙解释一下,谢谢!


    ----------------+----------------------------------------------------------+---------------------------------
          HashCode  |    GUID                                                                        |  Time                     
    ----------------+----------------------------------------------------------+---------------------------------
    1926873566    FBF88678-8B21-47BC-9B24-026380CE381A    2015-08-05 22:04:48.517
    1926873566    7AFF8FB6-8D26-4E0B-91C8-8524F8BA3163    2015-08-05 22:04:41.227
    193008853    A49B5FD0-6E1A-4BAD-A0F7-C10D17F1ECA8    2015-08-05 22:03:27.697
    193008853    DFBA50F9-C63B-4430-8CED-128AC4C4F21C    2015-08-05 22:06:05.480
    814270309    B91E8D70-E196-4AA2-B5CE-688533D9C7B7    2015-08-05 22:05:46.130
    814270309    AB8E851D-8A06-421A-BA82-11ECC587BA62    2015-08-05 22:07:28.980
    855610594    955CDBE6-E6A3-4F0B-A0D4-41992BD9210F    2015-08-05 22:04:18.027
    855610594    2278D4F4-2387-402F-AD08-33E867F25439    2015-08-05 22:05:15.490
    596747923    99A7ED3C-FB36-4BE7-B614-41B106840248    2015-08-05 22:03:09.200
    596747923    A4F7EF90-7D66-4967-A35F-FA26D7B42864    2015-08-05 22:07:24.907
    1605894372    F6FE4D3C-1C46-4D30-9509-B556B9FB8AE8    2015-08-05 22:04:26.340
    1605894372    D1ED496F-5255-4990-AA36-DCA627EC8A1B    2015-08-05 22:07:00.253
    1866874650    186A7EA6-4D2C-416F-83FD-3A9F9EBFBED3    2015-08-05 22:03:37.790
    1866874650    27347D80-8972-4209-A599-C109EE149493    2015-08-05 22:05:58.863







    • 已编辑 stoneca 2015年8月5日 14:16
    2015年8月5日 14:15

答案

  • 楼主,你应当尝试使用GetHashCode而不是ToHashCode方法,我不知道为什么你的Guid会有这个方法,我用net 4.5无这个方法。

    另外查源代码,Guid的源代码如下:

    public override int GetHashCode()
            {
                return this._a ^ (this._b << 16 | (ushort)this._c) ^ (this._f << 24 | this._k);
            }

    此外,不同的Guid值生成的GetHashCode应该是不同的(虽然我承认Guid不保证唯一,但是重复性应该不会像你列出的一样,会出现那么多频繁的重复):

     for (int i = 1; i < 11; i++)
                {
                    Guid newGuid = Guid.NewGuid();
                    Console.WriteLine(newGuid + "<==>" + newGuid.GetHashCode());
                }

    【结果】

    如果你一定要保证不重复,不如:

    1)把Long的字段设置成增长列,且步长为1.

    2)设计一个算法,保证不重复(例如):

     static string GetUnqiueLong()
            {
                Thread.Sleep(1);
                return DateTime.Now.ToString("yyyyMMddHHmmssfffffff");
            }
    
            static void Main(string[] args)
            {
                for (int i = 1; i < 11; i++)
                {
                    Console.WriteLine(GetUnqiueLong());
                }
            }

    ASP.NET Forum
    Other Discussion Forums
    FreeRice Donate
    Issues to report
    Free Tech Books Search and Download

    2015年8月14日 6:55
    版主

全部回复

  • GetHashCode从来就不保证唯一性。

    话说回来,Guid也是一样啊。



    Visual C++ MVP

    2015年8月5日 15:32
    版主
  • 真的吗?Guid难道不保证唯一性吗?(至少不唯一的概率基本可以忽略)

    如果一定要用long的话,可以用Interlocked.IncrementAllocateLocallyUniqueId,或者自己设计一个方法。

    不过这么看Guid.GetHashCode()的实现不太好啊。


    Not so sure what to write here.

    2015年8月12日 11:43
  • Guid的可能性肯定比Int的可能性多很多,因此HashCode有重复是必然的。
    2015年8月12日 23:43
  • 楼主,你应当尝试使用GetHashCode而不是ToHashCode方法,我不知道为什么你的Guid会有这个方法,我用net 4.5无这个方法。

    另外查源代码,Guid的源代码如下:

    public override int GetHashCode()
            {
                return this._a ^ (this._b << 16 | (ushort)this._c) ^ (this._f << 24 | this._k);
            }

    此外,不同的Guid值生成的GetHashCode应该是不同的(虽然我承认Guid不保证唯一,但是重复性应该不会像你列出的一样,会出现那么多频繁的重复):

     for (int i = 1; i < 11; i++)
                {
                    Guid newGuid = Guid.NewGuid();
                    Console.WriteLine(newGuid + "<==>" + newGuid.GetHashCode());
                }

    【结果】

    如果你一定要保证不重复,不如:

    1)把Long的字段设置成增长列,且步长为1.

    2)设计一个算法,保证不重复(例如):

     static string GetUnqiueLong()
            {
                Thread.Sleep(1);
                return DateTime.Now.ToString("yyyyMMddHHmmssfffffff");
            }
    
            static void Main(string[] args)
            {
                for (int i = 1; i < 11; i++)
                {
                    Console.WriteLine(GetUnqiueLong());
                }
            }

    ASP.NET Forum
    Other Discussion Forums
    FreeRice Donate
    Issues to report
    Free Tech Books Search and Download

    2015年8月14日 6:55
    版主