繁体   English   中英

BitSet 值得使用吗?

[英]Is BitSet worth using?

我制作了一个包含很多布尔字段的 Java 对象。 当我开始质疑它的实用性时,我正在考虑使用BitSet

当然,人们会出于内存原因使用它,因为boolean只有 8 位,数组中有 4 位。 使用BitSet ,每个值都存储为一个位。 但是,节省下来的内存不会被下面的开销吹走吗?

  • BitSet类和方法定义元数据(每个运行时)
  • 需要作为键来语义检索值的对象(每个类使用BitSet
  • BitSet bits组的元数据(每个实例)

与使用boolean s:

  • 布尔值(每个实例)

我们来看看下面的类:

private boolean isVisible; // 8 bits per boolean * 82 booleans = ~0.6Kb
// 81 lines later...
private boolean isTasty;

// ...

public boolean isVisible() { return isVisible; }
// ...
public boolean isTasty() { return isTasty; }

public void setVisible(boolean newVisibility) { isVisible = newVisibility; }
// ...
public void setTasty(boolean newTastiness) { isTasty = newTastiness; }

现在,如果我要将所有boolean组合成一个BitSet并且仍然保持我的代码语义,我可能会这样做:

private static final int _K_IS_VISIBLE = 1; // 32 bits per key * 82 keys = ~2.5Kb
// ...
private static final int _K_IS_TASTY = 82;
private BitSet bools = new BitSet(82); // 2 longs = 64b

// ...

public boolean isVisible() { return bools.get(_K_IS_VISIBLE); }
// ...
public boolean isTasty() { return bools.get(_K_IS_TASTY); }

public void setVisible(boolean newVisibility) { bools.set(_K_IS_VISIBLE, newVisibility); }
// ...
public void setTasty(boolean newTastiness) { bools.set(_K_IS_TASTY, newTastiness); }

tl;博士

costOfUsingBitSet =
    bitSetMethodsAndClassMetaData + // BitSet class overhead
    (numberOfKeysToRetrieveBits * Integer.SIZE) + // Semantics overhead
    (numberOfBitSetsUsed * floor((bitsPerBitSet / Long.SIZE) + 1)); // BitSet internal array overhead

并且可能更多。 而使用boolean s 将是:

costOfBooleans = 
    (numberOfBooleansOutsideArrays * 8) + 
    (numberOfBooleansInsideArrays * 4);

我觉得BitSet的开销要高得多。 我对吗?

BitSet将减少内存,仅使用一位更有效。 您正在查看的方法开销是一次,无论您的班级有多少实例,因此其成本基本上摊销为0

boolean相对于booleanBitSet数组的优点是它不是一个Object ,所以你有一个较少的间接层

高速缓存命中是性能的主要驱动因素,因此您必须权衡较少的高速缓存命中率,以及由于更高的内存消耗而从高速缓存中逐出数据的可能性更高

粗略地说,一些boolean会更快但内存更多,因为你有更多的字段或更接近大数字,比例将BitSet

boolean[]BitSet之间的空间比较不错:

https://www.baeldung.com/java-boolean-array-bitset-performance

图表 认为他们在这里交换了标签。 BitSet每个内存(蓝色)应该有更多位。

这里的关键要点是,除了最少的位数外,BitSet 在内存占用方面优于 boolean[]。

您的示例中的另一种方法是使用 2 long作为位标志。

class A {
// 1st set
private static final long IS_VISIBLE_MASK = 1; 
...
private static final long IS_DARK_MASK = 1 << 63 ; 

// 2nd set...
private static final long IS_TASTY_MASK = 1;
...

// IS_VISIBLE_MASK .. IS_DARK_MASK
long data1;

// IS_TASTY_MASK ...
long data2;

boolean isDark = (data1 & IS_DARK_MASK) != 0; 

}

暂无
暂无

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

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