存储“180位”(超过64位)整数的有效方法

时间:2014-10-20 21:14:05

标签: java performance bit-manipulation java-8

我使用位来表示一天发生的事件。例如,如果我存储4天的信息,我可以使用1011(从右到左盯着)将在第1,2天指示,并且发生了4个事件(第1,2和4个设置)。

我使用Long的类型来存储位(在本例中将存储数字11)。现在使用Long我可以存储63天的事件(长最大大小为2 ^ 64 -1)。

仅供参考:我稍后在我的一系列事件中选择一个,然后将其与另一组进行比较,以查看同一天发生了多少事件(我使用Long的bitcount方法来执行此操作)。例如,1011 AND 1000 = 1事件发生在这两组中的同一天。

我面临的问题是:我现在需要存储超过63天的数据。我现在需要大约180天。我遇到了两个解决方案的性能问题,并且想知道是否有更有效的方法来存储“180位”整数。

我的第一个解决方案是使用BigInteger,但这在运行时非常慢。我的另一个解决方案是将180位分解为3 Long并稍后进行比较,但显然这会产生3倍的工作。

3 个答案:

答案 0 :(得分:9)

java.util.BitSet

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文档中的一个示例将遍历bits1bits2中发生的所有事件:

for (int i = bits1.nextSetBit(0); i >= 0; i = bits1.nextSetBit(i+1)) {
     // operate on index i here
}

压缩位集JavaEWAH

请参阅: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倍。