Java 比特集值得使用吗?
我制作了一个Java对象,它有很多布尔字段。当我开始质疑它的有用性时,我正在考虑使用它 当然,出于内存原因,可以使用它,因为Java 比特集值得使用吗?,java,memory-management,bitset,Java,Memory Management,Bitset,我制作了一个Java对象,它有很多布尔字段。当我开始质疑它的有用性时,我正在考虑使用它 当然,出于内存原因,可以使用它,因为布尔值是8位,一个数组中有4位。使用位集,每个值存储为单个位但是,节省下来的内存不是会被以下开销吹出水面吗? 位集类和方法定义元数据(每个运行时) 语义检索值所需的键对象(每个类使用位集) 位集中位数组的元数据(每个实例) 与使用booleans相比: 布尔值(每个实例) 让我们看一下下面的课程: 私有布尔值可见;//每布尔值8位*82布尔值=~0.6Kb //8
布尔值是8位,一个数组中有4位。使用位集
,每个值存储为单个位但是,节省下来的内存不是会被以下开销吹出水面吗?
位集
类和方法定义元数据(每个运行时)
- 语义检索值所需的键对象(每个类使用
位集
)
位集中位
数组的元数据(每个实例)
与使用boolean
s相比:
- 布尔值(每个实例)
让我们看一下下面的课程:
私有布尔值可见;//每布尔值8位*82布尔值=~0.6Kb
//81行之后。。。
私人住宅;
// ...
公共布尔值isVisible(){return isVisible;}
// ...
公共布尔值isTasty(){return isTasty;}
public void setVisible(布尔newVisibility){isvisibility=newVisibility;}
// ...
public void setTasty(布尔newTastiness){isTasty=newTastiness;}
现在,如果我将所有的布尔值
组合成一个位集
,并且仍然保持代码的语义,我可能会这样做:
private static final int\u K\u是可见的=1;//每个密钥32位*82个密钥=~2.5Kb
// ...
私有静态final int_K_是_TASTY=82;
私有位集bools=新位集(82);//2长=64b
// ...
公共布尔值isVisible(){return bools.get(_K_IS_VISIBLE);}
// ...
公共布尔isTasty(){return bools.get(_K_是_TASTY);}
public void setVisible(boolean newVisibility){bools.set(_K_是_visibility,newVisibility);}
// ...
public void setTasty(boolean newTastiness){bools.set(_K_IS_TASTY,newTastiness);}
tl;博士
costOfUsingBitSet=
bitSetMethodsAndClassMetaData+//位集类开销
(numberOfKeystreeveBits*Integer.SIZE)+//语义开销
(使用的比特数*地板((比特比特比特集/长尺寸)+1));//位集内部数组开销
还有可能更多。而使用boolean
s将是:
costOfBooleans=
(BooleanSoutSideArray的数量*8)+
(BooleansInSideArray的数量*4);
我觉得位集的开销要高得多。我说得对吗?
位集
的内存会更少,只使用一个位的效率要高得多。不管您的类有多少个实例,您所看到的方法开销都是一次性的,因此它的成本基本上分摊到0
与布尔
数组或位集
相比,布尔
的优势在于它不是对象
,因此间接寻址级别减少了一个级别
缓存命中率是性能的主要驱动因素,因此您必须权衡缓存命中率越低,由于内存消耗越高,从缓存中逐出数据的可能性越高
粗略地说,几个boolean
s会更快,但内存会更多,因为您有更多的字段或更接近于巨大的数字,规模会朝位集的方向上升,您指出的内存开销不会存在于堆中,除非方法使用内部变量,如果您担心的话。此外,我们谈论的不是兆字节的内存消耗,而是位。除非你像心脏起搏器的软件一样构建一个关键的内存系统,否则这种担心是毫无价值的。@LuiggiMendoza我只关心整个系统的内存。这是Android的,所以我必须考虑512MB的设备。我们的应用程序已经非常庞大,因此,如果我们在整个过程中都使用这种方法,那么任何瘦身的方法都会有很大帮助。不管怎样,我的问题是:BitSet
有什么好处?好吧,在阅读了Java 1.6的BitSet
源代码之后,唯一会影响内存的字段是private long[]words
,private transient int wordsInUse=0
和私有瞬态布尔值sizeIsSticky=false代码>。您正在讨论的所有其他内容都应该已经由JVM为您加载,因此没有问题。我不会使用BitSet
替换常量boolean
s,只有在我可以拥有任意多个的情况下——例如,如果我替换任意Set
。我不理解。在这两种情况下,您都可以为密钥指定名称。您还忽略了位集的空间效率和容量都比布尔数组大得多。你在比较苹果和桔子,你也在匆忙下结论;如果是,我会询问只执行bools.set(1,false)所需的计算量代码>位集将减少内存,只使用一个位的效率要高得多当然,我知道进去;这就是我考虑的原因。我问这个问题的原因是因为我担心在这1位周围会发生什么(长long
s中未使用的位,长long
s存储在其中的数组的元数据,BitSet
类及其数组的元数据,int
s需要作为检索位的键,等等)@如果你看到源代码,你会发现开销是不值得关注的。但同样,除非通过使用探查器证明自己使用其中一个最适合您的情况,否则您无法确定。@Suphustar“long中未使用的位”在您的示例中占7个字节,占一个长字节的7个字节,或总共8个字节。您的82个布尔数组占用82个字节。”需要作为键的int
是局部变量,而不是实例变量,我无法理解您为什么会有不同的想法。