java – 压缩数字数组

我有一个大数组(~400.000.000个条目),整数为{0,1,…,8}.
所以每个条目我需要4位.大约200 MB.

目前我使用字节数组并在每个条目中保存2个数字.

我想知道,如果有一个好的方法,压缩这个数组.我做了一个快速研究,发现了像Huffmann或LZW这样的算法.但这些算法都用于压缩数据,将压缩数据发送给某人并解压缩.

我只想拥有一个具有较少内存空间的表,因此我可以将其加载到RAM中. 200MB的桌子很容易适合,但我正在考虑更大的桌子.

重要的是,我仍然能够确定某些位置的值.

有小费吗?

更多的信息:
我刚做了一点实验,事实证明,平均2.14个连续数字具有相同的值.
有1个零,154个,10373个,385990个三分,8146188个,85008968个,265638366个六,70791576个七和80个八个.
所以超过一半的数字是6s.

我只需要一个快速的getValue(idx)功能,setValue(idx,value)并不重要.

解决方法

这取决于您的数据的样子.是否有重复的条目,或者它们只是缓慢地改变,或者是什么?

如果是这样,您可以尝试压缩数据块并在需要时解压缩.块越大,可以节省的内存越多,速度越差.恕我直言没什么好处.您还可以将数据压缩并解压缩到内存中.

否则,即,如果没有规律性,每个条目至少需要log(9)/ log(2)= 3.17位,没有什么可以改善它.

通过将5个数字打包成一个短数,你可以非常接近这个值.如9 ** 5 = 59049< 65536 = 2 ** 16,几乎完美.你需要每位数3.2位,没有大赢.通过该公式给出五个数字的包装

a + 9 * (b + 9 * (c + 9 * (d + 9 * e)))

并且通过预先计算的表来解压缩是微不足道的.

问题更新后更新

Further information: I just did a little experimenting,and it turns out,that on average 2.14 consecutive numbers have the same value. There are 1 zero,154 ones,10373 twos,385990 threes,8146188 fours,85008968 fives,265638366 sixes,70791576 sevens and 80 eights. So more than half of the numbers are 6s.

事实上平均有大约2.14个连续数字是相同的可能导致一些压缩,但在这种情况下它没有说什么.几乎只有五个和六个,所以似乎暗示了遇到两个相等的连续数字.

鉴于这一事实,您可以忘记我的上述优化.由于您可以单独处理单个零,因此实际上只有8个值.因此,每个值只需要3位,零点需要一个索引.

您甚至可以为低于4或高于7的所有值创建HashMap,存储1 154 10373 385990 80个条目,每个值仅使用2位.但这还远非理想.

假设没有规律性,你需要每个值1.44位,因为这是entropy.你可以浏览所有5元组,计算它们的直方图,并使用1个字节来编码255个最频繁的元组.所有剩余的元组都将映射到第256个值,告诉您必须在HashMap中查找稀有元组值.

一些评价

我很好奇它是否可行.将5个数字打包成一个字节需要85996340个字节.有近500万个元组不适合,所以我的想法是为它们使用哈希映射.假设重新开始而不是链接它是有意义的保持它可能50%满,所以我们需要1000万条目.假设TIntShortHashMap(将索引映射到元组),每个条目占用6个字节,导致60 MB.太糟糕了.

一个字节中只包含4个数字,消耗107495425个字节,并留下159531个不适合的元组.这看起来更好,但是,我确信更密集的包装可以得到很大改善.

由这个小program产生的结果:

*** Packing 5 numbers in a byte. ***
normal packed size: 85996340.
Number of tuples in need of special handling: 4813535.

*** Packing 4 numbers in a byte. ***
normal packed size: 107495425.
Number of tuples in need of special handling: 159531.

相关文章

HashMap是Java中最常用的集合类框架,也是Java语言中非常典型...
在EffectiveJava中的第 36条中建议 用 EnumSet 替代位字段,...
介绍 注解是JDK1.5版本开始引入的一个特性,用于对代码进行说...
介绍 LinkedList同时实现了List接口和Deque接口,也就是说它...
介绍 TreeSet和TreeMap在Java里有着相同的实现,前者仅仅是对...
HashMap为什么线程不安全 put的不安全 由于多线程对HashMap进...