我使用位来表示一天发生的事件。例如,如果我存储4天的信息,我可以使用1011(从右到左盯着)将在第1,2天指示,并且发生了4个事件(第1,2和4个设置)。
我使用Long
的类型来存储位(在本例中将存储数字11)。现在使用Long
我可以存储63天的事件(长最大大小为2 ^ 64 -1)。
仅供参考:我稍后在我的一系列事件中选择一个,然后将其与另一组进行比较,以查看同一天发生了多少事件(我使用Long的bitcount方法来执行此操作)。例如,1011 AND 1000 = 1
事件发生在这两组中的同一天。
我的第一个解决方案是使用BigInteger
,但这在运行时非常慢。我的另一个解决方案是将180位分解为3 Long
并稍后进行比较,但显然这会产生3倍的工作。
答案 0 :(得分:9)
BitSet是标准库的一部分,适用于您的用例。但也许你应该看看下面的第二个选项是压缩的替代选择。这应该是更多的内存和性能效率。
使用标准库,您可以定义类似
的内容BitSet bits1 = new BitSet(180);
即使存储超过180位,您也可以随时调整其大小。
如果你想将它与其他套装进行比较,你可以这样做:
BitSet bits1 = new BitSet(180);
BitSet bits2 = new BitSet(180);
// do something here to set events
// find events which happened on the same day in bits1 and bits2
bits1.and(bits2);
然后你可以使用类似nextSetBit的东西来遍历集合。 Oracle文档中的一个示例将遍历bits1
和bits2
中发生的所有事件:
for (int i = bits1.nextSetBit(0); i >= 0; i = bits1.nextSetBit(i+1)) {
// operate on index i here
}
请参阅:Github repository for javaewah
在Apache Hive和Apache Spark等一些大数据项目中使用的Java BitSet的替代方案。
使用JavaEWAH的示例:
EWAHCompressedBitmap eventsBitmap1 = EWAHCompressedBitmap.bitmapOf(
0,1,22,64,1<<30);
EWAHCompressedBitmap eventsBitmap2 = EWAHCompressedBitmap.bitmapOf(
1,3,64,1<<30);
System.out.println("Events 1: "+eventsBitmap1);
System.out.println("Events 2: "+eventsBitmap2);
查找同一天发生的事件
EWAHCompressedBitmap bothEventsBitmap = eventsBitmap1.and(eventsBitmap2);
System.out.println("Days where both events took place: "+bothEventsBitmap);
答案 1 :(得分:1)
听起来你需要任意精度,你可以使用BigInteger
提供不可变的任意精度整数,
BigInteger val = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE);
System.out.println(val);
输出
9223372036854775808
答案 2 :(得分:0)
如果您的位组稀疏,则显式枚举“&#39;可能是有利的(在您的示例中,您将整数1,2和4存储为三个字节,前面有一个计数或后跟一个终结符字节 - &gt; n个(= 3)需要n + 1个字节(= 4)而不是23。
只要平均数小于23,这种表示就更紧凑。根据您执行的操作,可能会更慢或更快。
无论如何,处理可变长度表示可能很困难,特别是如果它是动态的。
显式位集表示通常是首选,但如果您的事件分布需要它,则也可以使用混合表示(例如,10个或更少的枚举,否则设置位)。
在您需要更紧凑表示的可怕情况下,霍夫曼熵编码可以帮助您再压缩2或3倍。