今天接到一家公司的面试邀请,于是我来到了这家公司,前台的小姐姐面带微笑地把我请进会议室,等待了一会,一位面试官走了进来……
在进行了简单的自我介绍之后,面试官开始发问了……
面试官:你好,请你使用最少的存储空间,记录一个用户在一个月内的登录记录,只需要知道用户在某一日是否登录即可。
我(略作沉思):好的,我们可以建立一张登录日志表,在用户登录的时候,记录一条登录日志数据,这张表和用户表是一对多的关系,有用户主键、登录类型、登录时间等等,如果有需要,我们还可以记录用户的登录 IP、登录国家、城市等等信息……
面试官(面无表情):……好的,请你回去等我们的通知吧……
我:……开玩笑的,既然要使用最少的存储空间来实现这个需求,使用传统的数据库记录登录日志的方式自然是难以达到这个条件的,所以我们需要打破传统的存储方式来实现这个需求。
面试官(略有兴趣):哦,那你要怎么实现呢?
我:总所周知,在 Java 中,一个 int 类型所占的内存空间是 4 个字节,而一个字节是 8 个 bit,所以一个 int 类型的数据,所占用的内存空间是 32 个 bit 位,而我的想法就是,使用一个 int 类型的数据,也就是 32 个 bit 位记录用户在一个月内的登录记录。
面试官(点了点头):32 个 bit 位,这个存储空间确实非常少,但是具体要怎么实现呢?你详细说说。
我:我之前也说了,一个 int 类型的数据,占用的内存空间是 32 个 bit 位,而 Java 中的 int 是一个有符号位的数据,除去最高位的符号位之外,在 Java 中一个 int 类型的数据,能够表达状态的一共有 31 个 bit 位。例如,一个值为 0 的 int 类型数据,转换为二进制的 bit 位,显示为 00000000 00000000 00000000 00000000
。
面试官满意地点了点头……
我:一个 int 类型的 bit 为可以有 0 和 1 两个状态,而且恰好有 31 个 bit 位可用,我们完全可以使用这 31 个 bit 位来记录用户当日是否登录。比如一个用户在 3 号登录了,使用 bit 位表示为: 00000000 00000000 00000000 00000100
。而后这个用户在 5 号也登录,使用 bit 位可以表示为: 00000000 00000000 00000000 00010100
。依次类推,一个月最多也就 31 天,假如一个用户在一个大月中每天都登录,使用 bit 位可以表示为: 01111111 11111111 11111111 11111111
。最后,我们将这个二进制的 bit 数据转换为 int 类型即可。
面试官:思路不错,但是具体要怎么实现呢?如果将一个 int 类型的数据转换为二进制的 bit 位数据,具体的算法实现会不会非常麻烦呢?程序的执行效率会不会很慢呢?
我(面带自信):我的实现很简单,而且程序的执行效率也非常快,甚至要比 Java 中的其他运算都要快!
面试官:哦……
我:我的实现方式,就是使用 Java 中的位运算来实现,使用位运算,不仅实现简单,而且运行效率远比其他符号运算快!
面试官(递过来一张纸):请你在草稿纸上简单实现一下吧。
我:……
我:首先定义一个私有的 int 类型的数据。
1 | private static int login = 0; |
我:其次,我们需要两个公有的方法,用来操作这个 int 类型的数据。
1 | public static void setBit(int bitIndex) { |
我:最后,我们可以测试一下这个方法。
1 | public static void main(String[] args) { |
我:在这段代码中,我没有对日期进行一个真实数据的维护,比如 1 号对应的是 0 位的 bit 位,31 号对应的是 30 位的 bit 位,所以在正式使用的时候,需要手动对真实的日期数据进行 -1 维护。
面试官(面露微笑):精彩!精彩啊!很好,我们公司就需要你这也的人才,明天来我们公司报道吧!
我(激动):好的,请问我的薪资是……
面试官(沉吟片刻):就 3k 吧。
我:……&#¥$@@*&^%……