【问题标题】:Unique ID generation Algorithm唯一 ID 生成算法
【发布时间】:2015-02-03 12:09:00
【问题描述】:

我在我的项目中找到了用于生成 PK 的代码,但我根本无法理解该代码的作用。

谁能给我一些指导或想法或解释?

        Integer typecode = ((AbstractEntity)object).getTypeCode();//this is unique number for every type
        Long counter = Long.valueOf(this.fetchNextCounter(typecode.intValue())); //this returns a counter for each type 
        Integer clusterid = Integer.valueOf(0);
        Integer millicnt = Integer.valueOf(0);
        Long creationtime = Long.valueOf((new DateTime()).getMillis());
//here is where the magic starts and I cant simply understand a thing            
if(typecode.intValue() >= 0 && typecode.intValue() <= 32767) {
                long longValue = counter.longValue() << 15 | (long)typecode.intValue() << 48 & -281474976710656L;
                longValue += ((long)clusterid.intValue() & 15L) << 44 & 263882790666240L;
                longValue += creationtime.longValue() - 788914800000L << 4 & 17592186044400L;
                longValue += (long)(clusterid.intValue() >> 2) & 12L;
                longValue += (long)millicnt.intValue() & 3L;
                longValue &= -8796093022209L;

                return Long.valueOf(longValue);
            } else {
                throw new RuntimeException("illegal typecode : " + typecode + ", allowed range: 0-" + 32767);
            }

我会感谢所有可以提供帮助的人?我们遇到的问题是我们的类型代码大于 32767,并且算法显示这不起作用,但为什么以及如何更改它?

【问题讨论】:

    标签: java algorithm bit-manipulation uniqueidentifier unique-key


    【解决方案1】:

    逐行(添加澄清括号):

    long longValue = counter.longValue() << 15 | (((long)typecode.intValue() << 48) & -281474976710656L);
    

    它计算两个值的二进制或:

    • counter 左移 15 位

    • typecode 左移 48 位并应用掩码 -281474976710656(与 0xFFFF000000000000 相同)。这个面具似乎是多余的。

    -

    longValue += (((long)clusterid.intValue() & 15L) << 44) & 263882790666240L;
    

    它获取clusterid的最后4位(&amp; 15,与&amp; 0xF相同),将其左移44位,然后应用掩码263882790666240L,即与0xF00000000000相同。最后一个面具应用似乎是多余的。将其与结果相加。

    longValue += ((creationtime.longValue() - 788914800000L) << 4) & 17592186044400L;
    

    它将creationtime 减去 788914800000L(即 12/31/1994 @ 11:00pm (UTC) 的时间戳),左移 4 位,然后应用掩码 17592186044400L,与 0xFFFFFFFFFF0 相同。将其与结果相加。

    longValue += (long)(clusterid.intValue() >> 2) & 12L;
    

    然后它获取集群 id,丢弃最后 2 位 (&gt;&gt; 2) 并应用掩码 12L,这与获取第 3 位和第 4 位(原始数字中的第 5 位和第 6 位)相同。将其与结果相加。

    longValue += (long)millicnt.intValue() & 3L;
    

    它获取millicnt (&amp; 3L) 的最后 2 位。将其与结果相加。

    longValue &= -8796093022209L;
    

    然后它将掩码-8796093022209L 应用于reslt,这与0xFFFFF7FFFFFFFFFF 相同。实际上,它会将结果数的第 44 位归零。

    【讨论】:

      【解决方案2】:

      运算符 >, |和 & 都是按位运算符。作用于这些数字的基础二进制值的各个位。如需更多信息,请阅读this 文章。然后取一个样本值并处理代码。

      【讨论】:

        【解决方案3】:

        这段代码将 typecode、counter、longvalue、creationtime、clusterid 和 millicnt 的位表示部分放在一起。这将创建一个唯一的新数字,因为以上所有内容的组合都是唯一的。但是,值的打包方式确实意味着您不能拥有超过 32767 个类型代码。就是空间不够。

        您可以通过Long.toBinaryString()查看输入的位表示以及每一步之后的longValue的详细信息。

        由于这些是数据库的主键,我认为您可以让数据库为您生成键。

        【讨论】:

          猜你喜欢
          • 2010-12-31
          • 1970-01-01
          • 2012-02-22
          • 1970-01-01
          • 2011-01-10
          • 1970-01-01
          • 2015-09-25
          • 1970-01-01
          相关资源
          最近更新 更多