Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java “有效的存储方式”;180位“;(大于64位)整数_Java_Performance_Bit Manipulation_Java 8 - Fatal编程技术网

Java “有效的存储方式”;180位“;(大于64位)整数

Java “有效的存储方式”;180位“;(大于64位)整数,java,performance,bit-manipulation,java-8,Java,Performance,Bit Manipulation,Java 8,我用位来表示一天中发生的事件。例如,如果我存储了4天的信息,我可以使用1011(从右向左看)来指示第1天、第2天和发生的4个事件(设置了位1、2和4) 我使用Long类型来存储位(在本例中存储数字11)。现在使用Long我可以存储63天的事件(Long max size为2^64-1) 仅供参考:我稍后在我的事件集上取一个,然后将其与另一个事件集进行比较,以查看同一天发生了多少事件(我使用Long的bitcount方法进行此操作)。例如,在这两组中,1011和1000=1事件发生在同一天 我面临

我用位来表示一天中发生的事件。例如,如果我存储了4天的信息,我可以使用1011(从右向左看)来指示第1天、第2天和发生的4个事件(设置了位1、2和4)

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

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

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

我的第一个解决方案是使用
biginger
,但运行时速度非常慢。我的另一个解决方案是将180位分解为3个
Long
s,然后进行相应的比较,但显然这会产生3倍的工作量

位集是标准库的一部分,适合您的用例。但也许你也应该看看下面的第二个选项,它是一个压缩的替代方案。这应该是更大的内存和性能效率

使用标准库,您可以定义如下内容

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);
然后你可以用类似的方法遍历集合。Oracle文档中遍历
位s1
位s2
中发生的所有事件的示例如下:

for (int i = bits1.nextSetBit(0); i >= 0; i = bits1.nextSetBit(i+1)) {
     // operate on index i here
}
压缩位集JavaEWAH 见:

在一些大数据项目(如ApacheHive和ApacheSpark)中使用的Java位集的替代方案

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);
进一步实施
  • ,也是一个压缩位图实现

听起来您需要任意精度,您可以使用它提供不可变的任意精度整数

BigInteger val = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE);
System.out.println(val);
输出为

9223372036854775808

如果您的位集是稀疏的,则显式枚举“1”可能是有利的(在您的示例中,您将整数1、2和4存储为三个字节,前面是计数或后面是终止符字节->n个(=3)需要n+1字节(=4)而不是23

只要平均数小于23,此表示形式就更紧凑。根据您执行的操作,它可以更慢或更快

无论如何,处理可变长度表示可能很困难,尤其是在它是动态的情况下

通常首选显式位集表示法,但如果您的事件分布需要显式位集表示法,也可以使用混合表示法(例如,枚举为10个1或更少,位集为其他形式)


在需要更紧凑表示的糟糕情况下,哈夫曼熵编码可以帮助您进一步压缩系数2或3。

java.util.BitSet如何首先我不了解您的存储方法,其次将其拆分为三个长的,不要使其慢三倍。在原语方面,您的选择是在各种整数数据类型。通过某种方式,您需要将值“拼接”在一起以获得180位。(注意:避免使用
boolean[]
,因为我看到的Oracle版本将boolean aray实现为每字节一位的字节数组。)否则,请使用java.util.BitSet或其他Set实现。(你说的毕竟是操作集合。)如果第三天或第五天发生了什么事情呢?这会被误解为分别发生在第1天和第2天,或第4天和第1天。我建议用布尔数组来代替。@YvesDaoust——我只记得36位逻辑(我想)但是,仔细想想,我认为CDC6600(我也使用过)有60位逻辑。Java的特点是,在Sun/Oracle实现中,甚至
布尔值
数组是每字节一位的(至少在几年前就已经存在了)。存储位集的效率非常低。感谢您的回复!我从未听说过JavaEWAH,但会看看并尝试实现它!做了一点研究后,我注意到了另一种选择,RoaringBitmap。我会尝试进行一点基准测试,但如果有人普遍知道哪种速度更快,那就太好了!@user2924127我将咆哮位图添加到答案中。咆哮位图仅支持一个对象的2^32-1
9223372036854775808