这篇文章源自一个需求的思考????。我们在日常开发可能会碰到类似这样的场景:
或者像这样:
他们的共同点是,一个页面/场景中包含多种状态。我们常用的做法是定义N个变量来保存各个的状态,eg. x1=是否允许向我提问、x2=是否允许短信提醒我、x3=是否允许电话提醒我、x4=是否允许发起语音通话。这样做的也没啥问题,结构清晰,也方便后续扩展,就是有点费键盘-要多敲好些下。其实除了这种方式之外,是否还有另外一种方式:通过一个变量来标记多个状态,答案是肯定的,那具体要怎么做呢?
我们先定义一个Number类型的正整数变量记作X,已知Number.MAX_SAFE_INTEGER最大值是9007199254740991,也就是253 - 1,把它转成二进制:
有没有发现,其实我们定义的X的转换成的二进制的每一位都是状态值(1-打开,0-关闭),最大可以表示53种状态,足够我们日常开发用了。有了这个思路后,后面就好处理了。
比如,我们想实现允许向我提问和允许电话提醒我,表示方式为:X= 0b0001 | 0b0010 = 0b0011 = 3
,服务端只需要返回一个数字3,我们这里就知道哪些开关是开启的了 (判断方式:eg.X & 0010 != 0
既说明该位状态是1)。
这种利用二进制位来解决一个变量处理多个状态的问题,我第一次也是在安卓源码里看到的,而且安卓里这一块的运用还是很普遍的,对应的状态值也有十几个,像下图这样的:
通过这样的操作,能很方便进行位的运算(AND/OR/XOR/NOT)。
其实说到二进制的运用,我们接触到第一个示例,可能是在学校期间学习C语言时的一个示例:《交换两个int变量值》
通过异或操作,在不新增变量的前提下交换了两个变量的值了(而且不用考虑精度丢失的问题)。
除了交换两个数,还有一个比较经典的【老鼠毒药】问题,一个比较经典的答案也是利用二进制的思路解决的。
有 1000 个一模一样的瓶子,其中有 999 瓶是普通的水,有一瓶是毒药。任何喝下毒药的生物都会在一星期死亡。现在,你只有 10 只小白鼠和一星期的时间,如何检验出哪个瓶子里有毒药?
读完这个题后,想必大家心中都有了解题思路。10只小白鼠,相当于有10个二进制位,能最大标识210=1024种状态,足够标识1000个瓶子了。
解题思路是:根据0-9编号小白鼠的死亡情况得到了一个二进制数,在转换成十进制,就能很容易得到是几号瓶的水有毒了,如上图。
这类基于二进制位的运算,用起来并不是太方便,在各个语言库里都能找到对应工具类库(三方或官方的)。记得Java util包里有个专门做这个的类:BitSet.java,当然JS也有,大家可以去找下。
上面说了这么,总结来说就是利用二进制的每位能够标示0-1两种状态来搞事情。有关这方面的使用,还有个更高级的名词:位图(Bitmap)。至于Bitmap是什么,能做哪些事,我们就放到后面的文章里去介绍了, 大家感兴趣可以网上搜搜看,相关的文章还是很多的。