二进制巧妙运用-二进制存多个布尔类型状态值

两个数交换位置:int a = 1;int b = 2;如何交换ab两个变量的值?

①使用第三个变量来接收

int c = 0;
c = a;  //c  等于1
a = b;  // a 等于2
b = c;  // b 等于1

当然灵活运用,这种方式肯定是不推荐的啦!
②刷新一下你对小学数学的理解

a = a + b;  // a 等于3
b = a - b;  // b 等于1
a = a - b;  // a 等于2

③既然是程序员,我们用程序员的方式来做一下,还可以深刻理解一下^

//如果m、n两个值不相同,则异或结果为1。如果m、n两个值相同,异或结果为0。
//1 的二进制 : 0000  0001
//2 的二进制 : 0000  0010
//3 的二进制 : 0000  0011
a = a ^ b;  // a 等于 1 ^ 2 = 0000 0011 = 3
b = a ^ b;  // b 等于 3 ^ 2 = 0000 0001 = 1
a = a ^ b;  // a 等于 3 ^ 1 = 0000 0010 = 2

是不是很奇妙。下面看一个一样奇妙的与& 、 或 | 的操作。

  • 我们经常会遇到需要存一组boolean值得时候,这些值有个特点,便是只有两种情况,要么true、要么false,或者说要么正确、要么错误,在或者说要么0,要么1。ok,就是这个01,也就是今天的主角,二进制。
    逢二进一,借一当二
    我们也可以把二进制想成一个盒子,一个容器,里面装的便是你要存储的boolean值。举个栗子,后台认证的时候,用户手机号是否认证,邮箱是否认证,是否实名认证,地址是否填了,紧急联系人是否填了,微信是否认证,QQ是否绑定,银行卡是否绑定……
    那么这个二进制容器就可以来装这些数据了,1就是已经放进盒子里面了,0就是没放进盒子里面。
手机号 邮箱 身份证 地址 紧急联系人 微信 QQ 银行卡
1 0 1 0 1 0 1 1
  • 下面讲解代码上怎么展现:
    讲之前先说& | 的用法吧
二进制中
  • 两个数都为1,&的值才为1,否则为0
    即数学中的同时成立,条件才成立
  • 两个数都为0,|的值才为0,否则为1
    即数学中的任意一个成立,条件便成立

好,现在进入正题

int bankCard = 1 ;
int QQ       = 2 << 0;
int weChat   = 2 << 1;
int person   = 2 << 2;
int idCard   = 2 << 3;
int addr     = 2 << 4;
int email    = 2 << 5;
int phone    = 2 << 6;

在将上面的这些值转换为二进制的数:

//不一定是8位的二进制数据,只是演示,节目效果
0000 0001:银行卡
0000 0010:QQ
0000 0100:微信
0000 1000:紧急联系人
0001 0000:地址
0010 0000:身份证
0100 0000:邮箱
1000 0000:手机号

那么转化为上面的格子的图,是不是就是这样。

手机号 邮箱 身份证 地址 紧急联系人 微信 QQ 银行卡
1 1 1 1 1 1 1 1

如果认证了手机号,就在手机号里面填1,没认证就是0,其他的也一样。

  • 向格子插入数据的时候:
int state= 0;  	        	
state = state | phone ;  	
·····························解析·····························
//0000 0000		——>state开始时候的二进制
//1000 0000		——>phone的二进制
//1000 0000		——>|(或)运算结果,state变成了1000 0000,从而实现存储
//实现了phone的存入,其他数据类似,
  • 从格子查询数据的时候:
int state = 10;    							
phone = state & phone;  
·····························解析·····························
//state为任意值,为了验证有绑定的,也有没绑定的,所以取个10。
//0000 1010		——>state=10的二进制
//1000 0000		——>phone二进制
//0000 0000		——>&(与)结果为0,说明还没有绑定手机
---------------------------------------------------------------
QQ = state & QQ ; 
·····························解析·····························
//0000 1010		——>state=10的二进制  	
//0000 0010		——>QQ二进制
//0000 0010		——>&(与)结果为 2 << 0,即QQ的二进制,说明已经绑定了QQ

综上所述,只要判断state&<变量名>是否为0,即可得出是否绑定
这样可存可取,是不是比原来声明8个boolean类型的变量要好呢?在我们阅读源码的时候也经常会遇到这样的存取方式,了解便好!
另外,还有一种情况,就是已经绑定了手机号,但是需要取消绑定,这个时候使用&|就不能达到需求了。这个时候就需要上面讲过的^。
还用state=10来举例子,已知10里面存入了‘QQ’和‘紧急联系人’,看看怎么取消QQ的绑定。

int state = 10 ;
state = state ^ QQ ; 
·····························解析·····························
//0000 1010		——>state=10的二进制  	
//0000 0010		——>QQ二进制
//0000 1000		——>^(异或)结果为2<<2,表示state仅剩紧急联系人,成功取消QQ

至此,使用二进制来存储数据就完整结束了,有更好的想法,更多的见解,更妙的猜想,更深的疑惑……欢迎评论,我们讨论、互相学习。

上代码

	/**
	 * @param states
	 *            当前状态值
	 * @param value
	 *            需要判断状态常量
	 * @return 是否存在
	 */
	public static boolean hasState(Integer states, Integer value) {
		return (states & value) != 0;
	}

	/**
	 * @param states
	 *            当前状态值
	 * @param value
	 *            需要添加状态常量
	 * @return 新的状态值
	 */
	public static Integer addState(Integer states, Integer value) {
		if (hasState(states, value)) {
			return states;
		}
		return (states | value);
	}

	/**
	 * @param states
	 *            当前状态值
	 * @param value
	 *            需要删除状态常量
	 * @return 新的状态值
	 */
	public static Integer removeState(Integer states, Integer value) {
		if (!hasState(states, value)) {
			return states;
		}
		return states ^ value;
	}

你可能感兴趣的:(巧妙运用)