一种通用整形数组压缩方法

我们在开发中后台应用或者中间件的时候,会存储一些数据在内存中以加快访问速度。随着数据量的增加,除了可以放置于堆外,还可以通过实时压缩来缓解。今天就给大家介绍一种压缩整形数组的方式。

一 数据压缩

数组指 long[] 或者 int[] 类型,在 Java 中应用很广。当数据量很大时,其内存占用的问题便突显出来,原因是一个 long 类型是占 8 个字节,而 int 也是占用 4 个字节,当有千万级别的数据时,其占用的空间便是上百 MB 级别的了。

1 去冗余

首先想到的就是缩减每个数字占用的空间。因为我们都知道就正数而言,int 3 个字节以上即可表示 2^24 = 16M 即 1600 百万个数,而再往后,即使用第 4 个字节,绝大多数我们是用不到的,但也不能砍掉,万一还会用到的;所以可以将高位去掉,是一种可行的思路,但必须动态去掉,该用的时候还是得用,这就需要存储用到多少个字节了(见图:数字压缩基本原理)。

数字压缩基本原理

表示数据占用字节数有两种方式:一是借用原数据的几位来表示,就拿 long 来说,我们只需要借用 3 位就可以覆盖用到的字节数了(因为 2ˆ3 = 8),由于 2^60 以后已经是非常大的数了,几乎用不到,所以我们借用也基本不会产生负面效果;另一种就是利用字节最高位表示还有剩余数据(见图2),Facebook 在 Thrift 中就是使用此方法来压缩传输数据的。总之,我们就是要把 long 或者 int 数组压缩成 byte 数组,在使用时再依据 byte 数组中存储的信息将对应的数字还原。

解压时识别数据大小方法

以上压缩思路在传输场景下可以很好的解决存取问题,因为都是前进先出的思路,但是如果我们需要压缩后的结构仍然具备数组的下标访问能力怎么办?

这里的难点是:之前每个数字都是固定长度,我们可以通过 “[单个数字占用的字节数]*[第几个]” 很快地找到对应的内存地址,但是压缩过后每个数字占用的空间不是一样的,这种方式就失效了,我们无法得知第 N 个数所处的内存位置。要取下标为 200 的值,难道只能线性查找 200 次吗?显然这样的效率是相当低的,其时间复杂度就由 O(1) 下降为了 O(n)。有没有更好的办法呢?当然是有的。我们可以建立索引(如下图),即:

  • 将数字分为若干个桶,桶的大小可心调节(比如可以 1KB 一个桶,4KB 一个桶等)
  • 我们使用另一个数组,大小为桶的数量,存储每个桶所第一个数据所在的下标
  • 在查找时我首先使用二分查找到对应的桶,再使用线性查找到对应的数据

带索引可提升压缩后下标获取速度

由于只是在桶内是线性查找,而其一般不会太大,为 1KB 或者 4 KB(不能太少,因为每个桶的数组指针也是需要占用 16B 的)。由于第一次的索引二分查找解决了大部分问题

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值