位掩码的介绍与使用

##一、小白鼠试毒
有1000瓶水,其中有一瓶有毒,小白鼠只要尝一点带毒的水24小时后就会死亡,问至少要多少只小白鼠才能在24小时鉴别出哪瓶水有毒,刚看类似的问题,一般人一定是一脸懵逼的状态的,分析一下,喝了带毒的水24小时才会毒发,目前需求是要24小时就要鉴别出来哪瓶有毒,所以小白鼠只够喝一次水的时间,完全摸不到头脑…
###解决办法
先直接来说解决问题的办法:将1000个瓶子使用二进制来标识,比如 1111101000 (第1000瓶)……0000000001 (第1瓶),将所有二进制码竖直排列,每个数字位对齐,然后开始取水的混合液,这个混合液取法,如下图,每个对应位置的数字包含1的都取1滴,这样就取出了10份混合液,顺序按照二进制数字位置摆放,拿10只小白鼠,每只一杯混合液喝下,24小时后,查看小白鼠情况,从左边第一个位置开始,如果小白鼠死了,混合液标记为1,否则标记为0,全部统计完成后的二进制码在转换成十进制,就是有毒的水
在这里插入图片描述
在这里插入图片描述

###解决思路
逻辑上来解释这个问题,首先看瓶子,二进制数,10位能够表示的最大数位2的10次方-1=1023,大于1000,所以足够覆盖1000以内的二进制展示,有毒的那瓶水的二进制插入在竖直排列的数据中,混合液为获取当前二进制位上为1的所有水的混合,当小白鼠喝了over以后,说明有毒的水当前二进制位上的数值是1,否则,说明当前二进制的数值为0,所以当小白鼠最终是否over,根据转换后的十进制就能获取到有毒的那瓶水

##二、位掩码介绍
这种处理问题的思路在java中有一个学名-位掩码,掩码(英语:Mask)在计算机学科及数字逻辑中指的是一串二进制数字,通过与目标数字的按位操作,达到屏蔽指定位而实现需求,java中有很多运算符,常用的有与(&)、非(~)、或(|)、异或(^)、移位(<<和>>)等,部分位操作如下:

非(~)
~ 0000 0001
= 1111 1110

使用
int a = 1;
int b = ~a;

或(|)
0000 0001
| 0000 0010
= 0000 0011

使用
int a = 1;
int b = 2;
int c = a | b;

与(&)
& 0000 0101
0000 0110
= 0000 0100

使用
int a = 5;
int b = 6;
int c = a & b;

Ps:以上例子源于网络
##位掩码使用介绍
bitmask中每个二进制位都有两种取值情况:0或者1,我们采用一个二进制位来记录状态,每一个二进制位表达一个状态,ps:这种做法相对于枚举(仅作用于表示状态的枚举)来说会更能节省内存,这样一个int型数据,可以表达32种状态,同时,也可以对多个状态进行CRUD的操作,常用的基本操作如下:
a&~b: 清除标志位b;
a|b: 添加标志位b;
a&b: 取出标志位b;
a^b: 取出a与b的不同部分;

举个例子,每个项目可能都会用到用户证件信息,当时不同的项目需要得到支持的证件不同,比如火车票使用身份证,机票可能需要身份证和护照,这里用两种实现方式做个比较,代码如下:

在这里插入图片描述
在这里插入图片描述

以上例子第一种方式使用四个boolean值来保存所能支持的证件。
第二种方式每种证件使用了一个二进制数位来表示是否支持当前证件
ID_CARD = 1 << 0 转换成 0001 左边数第一个二进制位表示为支持身份证
PASSPORT = 1 << 1 转换成 0010 左边数第二个二进制位表示为支持护照
falg存储了当前能够支持的证件类型

测试代码如下:
第一种boolean值使用方式

在这里插入图片描述

第二种二进制位标识使用方式

在这里插入图片描述

二进制打印结果如下:

在这里插入图片描述

由于直接打算int值,显示结果位10进制数,转换为二进制可以看到对应的二进制位支持证件的情况
##源代码中的位掩码使用
1、Class反射中的修饰符public、private等

在这里插入图片描述

上面看出在Modifier中使用二进制标识了不同的修饰符字段,源码使用如下:

在这里插入图片描述

2、Linkify中的文本类型url、电话、地址等

在这里插入图片描述

定义了Text的各种文本类型,通过判断不同的类型执行不同的Links方法处理

在这里插入图片描述

3、View中定义的可见值VISIBLE、INVISIBLE等

在这里插入图片描述

##总结
在 Android 的代码中有大量的 BitMask 的运用,像 View,MotionEvent ,使用BitMask能够减少内存的使用,不过只是相对来说,并不是不建议使用boolean值、枚举等方式来实现,每种方式都有自己的优势和特点,选择最适合的才是最重要的

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值