zoukankan      html  css  js  c++  java
  • 日期的压缩存储daybits

    问题:

    存储一个日期的序列,例如保存用户一年的登录时间序列,20140201,20130102这样两个日期,如果用INT那么需要八个字节,用STRING就更多了。

    解决:

    通过bit来存储一天,具体的组织形式是这样的

    struct daybits {

        Year[] before_years;

        Year[] after_years;

    }

    struct Year {

        Quarter q1;

        Quarter q2;

        Quarter q3;

        Quarter q4;

    }

    struct Quarter {

        byte[] bytes

    }

    日期压缩过程 

    daybits中有若干个年,以2013做为轴分别存储在before和after years数组里。每个年有四个季度,每个季度中有个byte数组,数组中的每个字节代表8天,bytes[i] 代表这个季度的第i*8 - (i+1) * 8天,其实就是Java BitSet不用INT存储,用BYTE存储。还有一点和JAVA的BitSet不同的是,Quarter中的byte数组,使用了延迟加载,当在某一个季度登录过,这个季度才分配存储空间,并且,分配的空间也不是每次把一个季度中的90天(假设一个月30天)全都分配了(最多也就是分配12个字节可以表示96天,够一个季度的天数了),而是最大需要多少天分配多少字节,如果这个季度之后的天又需要存储,那么重新分配空间再memcpy。通过这种分季度,节约了很大一部分的存储。如果一个季度登录过三天应该就比用INT存储登录时间要高效,如果是只登录了一天,而且是在季度的最后一天,那就亏了。

    例子


    存储20140105

    2014年存储在after_years[1]中

    1月存储year的q1中

    计算2014年1月1日的时间戳,计算2014年1月5日的时间戳,相减除以3600*24秒得到是1月的第五天

    存储在byte[0],且值为二进制的00010000,代表第五天

    反解的时候通过月的第N天解出是几月几日有点麻烦,如果有Java Calendar处理这个还比较简单,不过这个东西可以提前计算好

    daybits的ToString

    用"#",区分了上半区和下半区,用";"区分了每年,用","区分了每个季度,每个季度的bytes数组用base64编码。

  • 相关阅读:
    leetcode 131. Palindrome Partitioning
    leetcode 526. Beautiful Arrangement
    poj 1852 Ants
    leetcode 1219. Path with Maximum Gold
    leetcode 66. Plus One
    leetcode 43. Multiply Strings
    pytorch中torch.narrow()函数
    pytorch中的torch.repeat()函数与numpy.tile()
    leetcode 1051. Height Checker
    leetcode 561. Array Partition I
  • 原文地址:https://www.cnblogs.com/23lalala/p/4201153.html
Copyright © 2011-2022 走看看