使用bit位进行标识 - pod4g/tool GitHub Wiki

一、 问题引出

我们以一个数据表的设计为例,比如,一个程序猿表(rd),含有3个字段

ID Name Skill
主键 程序猿名字 会的技能

一个程序猿假设他的Skill为下列技能的一种或几种:

  1. Java
  2. JavaScript
  3. NodeJS
  4. HTML
  5. CSS
  6. MySQL
  7. Redis
  8. Linux

那么我们如何存储Skill比较好呢(比较好包括:1. CRUD方便;2. 用的存储量小; )

二、使用Bit位

上述问题,我们因为Skill可以有一种或多种,我们可以用一串Bit来标识,比如Skill的数据类型为MySQL的无符号tinyint,则含有8个Bit 我们从低位起,高位结束,会那项技能,就给那项置为1,其它位为0,则:

位置(从1开始) 含义
0000 0001 1 1 会Java
0000 0010 2 2 会JavaScript
0000 0100 3 4 会NodeJS
0000 1000 4 8 会HTML
0001 0000 5 16 会CSS
0010 0000 6 32 会MySQL
0100 0000 7 64 会Redis
1000 0000 8 128 会Linux

Bit操作都有那些:

  1. 按位与,符号为&
  2. 按位或,符号为|
  3. 按位取反,符号为~
  4. 异或,符号为xor
  5. 左移操作,符号为<<
  6. 右移操作.符号为>>

任意Bit位置0或置1,参考http://blog.csdn.net/xhfight/article/details/51537425

如果一个程序猿即会Java,又会JavaScript,那么这串Bit的第一位和第二位都为1,即0000 0011,值为3 如果一个程序猿很牛逼,所有技能都会,那么这串bit为,1111 1111,值为255 (可以把这个值想象成工资,会的越多,工资越高)

但是,值有了,我们如何确定一个程序猿是否会Java呢?

只要用 Skill & 1 === 1 则可以确定这个程序猿会Java

如果一个程序猿以前不会NodeJS,通过努力,学会了,则我们需要更新这位程序猿的Skill字段,把第三位也置为1,则可用Skill | 4即可

如果一个程序猿学习能力特强,一次性地学会了NodeJS、MySQL、Radis,则我们更新这位程序猿的Skill字段,把第三、第六、第七位都要置为1,则用 Skill | 196即可,那么这个196哪儿来的? 196 = 128 + 64 + 4

这些都是正常情况,如果一个程序猿年老色衰或太长时间没用某项技术,导致不会了,那么我们应该把代表这项技术的位置为0,比如这个程序猿不会Redis了,则Skill & ~(1 << (位置 - 1))即可

三、MySQL的CRUD例子

SELECT * FROM rd WHERE skill & 1 = 1;   -- 选出所有会Java的程序猿
SELECT * FROM rd WHERE skill & 16 = 16; -- 选出所有会CSS的程序猿
SELECT * FROM rd WHERE skill & 1 = 1 and skill & 16 = 16; -- 选出所有即会Java又会CSS的程序猿

UPDATE rd SET skill = skill | 1 WHERE id = 1;  -- 把ID为1的这个程序猿的skill更新为会Java
UPDATE rd SET skill = skill | 16 WHERE id = 1; -- 把ID为1的这个程序猿的skill更新为会CSS
UPDATE rd SET skill = skill | 196 WHERE id = 1; -- 把ID为1的这个程序猿的skill更新为会NodeJS、MySQL、Redis
UPDATE rd SET skill = skill & ~(1<<6) WHERE id = 1; -- 把ID为1这个年老色衰的程序猿的skill更新为不会Redis