繁体   English   中英

为什么 Java BitSet 打包成 6 个字节?

[英]Why is a Java BitSet packed in 6 bytes?

我正在研究BitSet ,但我不清楚以下几点:

  1. 当我们传递位数时,会除以6 为什么使用6而不是 2 的幂?
  2. 初始化底层数组时,为什么在除以6之前先减 1,然后加 1?

我假设您正在询问 JDK 中的这段代码:

private static int wordIndex(int bitIndex) {
    return bitIndex >> ADDRESS_BITS_PER_WORD; // ADDRESS_BITS_PER_WORD is 6, question 1
}

public BitSet(int nbits) {
    // nbits can't be negative; size 0 is OK
    if (nbits < 0)
        throw new NegativeArraySizeException("nbits < 0: " + nbits);

    initWords(nbits);
    sizeIsSticky = true;
}

private void initWords(int nbits) {
    words = new long[wordIndex(nbits-1) + 1]; // question 2
}

initWords初始化一个long[]来支持这些位,基本上将这些位存储到 64 位的“字”中。 请注意,这似乎是一个实现细节。 这个long[]应该有多长? 好吧,它应该是最后一个单词的单词索引+ 1,因为索引是从零开始的。

最后一个词的索引是多少? 嗯, wordIndex方法可以告诉我们一个的单词索引,所以如果我们给它最后一位的索引, nbits - 1 (同样因为索引是从零开始的),它会给我们想要的。 这应该回答你的第二个问题。

wordIndex如何找到单词索引? 嗯,一个long有 64 位,所以我们只需要将bitIndex除以 64。除以 64 的另一种方法是什么? 左移 6 次,因为 64 = 2 的 6 次方。有关更多信息,请参阅此帖子

我想你谈谈这个 class 的实现?

它在源文件的注释中这样说:

    /*
     * BitSets are packed into arrays of "words."  Currently a word is
     * a long, which consists of 64 bits, requiring 6 address bits.
     * The choice of word size is determined purely by performance concerns.
     */

因此,对于给定的位数,低 6 位用于寻址 64 位字的位,其余位用于寻址字。


对于第 2 点,我想你在谈论

wordIndex(nbits-1) + 1

这是

bitIndex >> ADDRESS_BITS_PER_WORD
  • 假设你想初始化一个最初有 0 个条目的 BitSet。 然后你需要一个大小为 0 的数组。
  • 假设您要初始化一个最初包含 1 到 64 个条目的 BitSet。 然后你需要一个大小为 1 的数组。
  • 假设您要初始化一个最初包含 65 到 128 个条目的 BitSet。 然后你需要一个大小为 2 的数组。

等等。

这意味着,您将 map 原始范围 (1-64, 65-128) 改为“减一” (0-63, 64-127),除以 64 (0, 1) 并再次增加结果 (1, 2)获取数组中所需单词的数量。


为了证明两者:

假设您想要一个包含 128 个条目的 BitSet。 你初始化它,你会得到一个包含 2 个 64 位条目的数组。 为什么?

这是因为 wach 字可以容纳 64 位,所以为了容纳 128 位,您需要 2 个数组条目:

(128-1)/64 + 1 = 127/64 + 1 = 1 + 1 = 2。(请记住,integer 将 go 划分为较低的值。)

现在,您要设置 bis 5、13 和 66。

第 5 位和第 13 位很好 - 您只需在索引 0 处设置字中的第 5 位和第 13 位。

但是你用 66 做什么呢? 每个字只有 64 位。 (0..63)

好吧,在这种情况下,您在数组中执行的每个步骤都减去 64。 所以你 go 到索引 1 处的单词和“补偿”,你 go 从 66 到 2。

这正是这些位操作所发生的事情:从这些位索引中的每一个,低 6 位被取出并用作相应字中的位地址。

5 = 0 000101 = 0/5 13 = 0 001101 = 0/13 66 = 1 000001 = 1/2

所以

  • 5 通过设置字 0 中的位 5 来设置。
  • 13 通过设置字 0 中的位 13 来设置。
  • 通过设置字 1 中的位 2 来设置 66。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM