boolean 与BitSet:哪个更有效?

什么是更有效的内存和CPU使用情况 – boolean s或BitSet数组? 没有使用特定的BitSet方法,只能得到/设置/清除(==,=,Arrays.fill分别为一个数组)。

从Sun JDK 1.6的一些基准testing中筛选出10个迭代(最好10次迭代进行预热,给JIT编译器一个机会,排除随机调度延迟,Core 2 Duo T5600 1.83GHz):

除了非常小的尺寸之外,BitSet比boolean []更具有内存效率。 数组中的每个布尔值都需要一个字节。 runtime.freeMemory()中的数字对于BitSet有点混乱,但less一些。

布尔型[]是更高的CPU效率,除非是非常大的尺寸,他们大约是偶数。 例如,对于一百万个布尔[],约快四倍(例如6ms vs 27ms),十亿和十亿大约是偶数。

  • Boolean[]使用每个布尔值大约4-20个字节。
  • boolean[]使用每个布尔值约1个字节。
  • BitSet每布尔值使用大约1位。

在这种情况下,内存大小对您来说可能不是问题,布尔型[]可能更容易编码。

你的问题有点左右,但如果存储是一个问题,你可能要考虑霍夫曼压缩 。 例如, 00000001可能被频率压缩到相当于{(7)0, (1)1} 。 一个更“随机”的string00111010将需要更复杂的表示,例如{(2)0, (3)1, (1)0, (1)1, (1)0} ,占用更多的空间。 根据您的位数据的结构,您可能会从BitSet获得一些存储利益。

它一如既往地依靠。 是的BitSet是更多的记忆效率,但只要你需要multithreading访问布尔[]可能是更好的select。 例如,计算素数只能将布尔值设置为true,因此您并不需要同步。 Hans Boehm已经写了一些关于这个的文章,同样的技术可以用来标记图中的节点。

至于内存, BitSet的文档有相当明确的含义。 尤其是:

每个比特集具有当前大小,这是由该比特集当前使用的空间的比特数。 请注意,大小与位集的实现有关,因此可能会随实现而改变。 位集的长度与位集的逻辑长度有关,并且与实现无关地定义。

Java库类的来源是公开可用的,您可以轻松地自行检查 。 尤其是:

 The internal field corresponding to the serialField "bits". 89 90 private long[] words; 

至于速度; 这取决于一个人在做什么。 一般来说,不要提前考虑速度, 使用哪个工具最有意义的语义,并导致最清晰的代码。 只有在观察到性能要求没有得到满足并找出瓶颈之后才进行优化。

来到SO并询问A是否比B更快是愚蠢的,原因很多,包括但不限于:

  1. 这取决于应用程序,通常无人应答的应用程序。 在正在使用的上下文中分析和分析它。确保这是一个实际上值得优化的瓶颈。
  2. 像这样询问速度的问题通常表明,OP认为他们关心效率,但不愿意描述性能,也没有定义性能要求。 在表面之下,这通常是一个红旗,OP是走向错误的道路。

我知道这是一个古老的问题,但最近出现了; 我相信这是值得补充的。

从Java到CPU是完全VM特定的。 例如,它曾经是一个布尔实际上被实现为一个32位值(很可能是真实的今天)。

除非你知道这个问题很重要,否则你最好把代码编写清楚一些,分析一下,然后修复速度较慢或消耗大量内存的部分。

你可以随你做。 例如,我曾经决定不要在string上调用.intern(),因为当我在分析器中运行代码时,它太慢了(尽pipe使用较less的内存)。

我相信BitSet更具内存和CPU效率,它可以在内部将这些位打包成int,long或native数据types,而boolean []则需要每一位数据的一个字节。 此外,如果您要使用其他方法(和等),则会发现BitSet更高效,因为不需要遍历数组中的每个元素; 按位math来代替。

Interesting Posts