绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
开发技巧:如何能一个字段表示八个状态?
2019-12-24 15:10:13

作者:锦成同学

一、惊现问题

有一天,突然来了一个需求,问小明提交了哪些课程的作业?

A:语文 B:数学 C:英语 D:物理 E:化学 F:生物 G:历史 H:地理 .....这么多课程.....我要8个字段? 万一还有课程呢?我还要再加字段?

我肯定不慌啊,我一个字段搞定。

二、解决之道

通过一个 int或者long 字段,来添加多个 标志或者状态. 一个int或者long字段,能够管理多个标记(状态)值. 如此神奇的操作怎样实现的呢? 答案就是通过位运算来实现.

像这种,独立状态(标记)之间相互组合可以产生新的状态(标记),且每个独立状态(标记)只有true或者false值的,我们可以使用位状态的概念来管理这些状态.

它的核心思想就是将, int 数值看做是 二进制数位表示.如果有四个状态就可以像这样 0000,用四位二进制表示,每一个二进制位都可以表示一种状态. 然后通过 位运算,来提取或添加标记位.四位对应的组合状态有16个. 而我们,只需要通过一个int变量就能够管理这些状态.

当参与的状态(标记)越多时,如果使用单独的标记变量,就需要生成越多的变量,而用位域,这种独立状态为不管有多少个,都可以用一个变量表示.int类型多存放32个独立状态.

位操作基础:

java中提供的基础位运算符有 与(&),或(|),非(~),异或(^),左移<<,右移(>>)和无符号右移(>>>).

除了位非(~)是一元操作符外,其它的都是二元操作符。

下面只介绍本文中,使用到的位操作:

1.位与

A & B : A和B对应的二进制数位都为1时,结果才为1,其他情况为0.

A = 001101 // 13

B = 100101 // 37

A & B = 000101 // 5

2.位或

A | B : A和B对应的二进制数位都为0时,结果才为0,其他情况为1.

A = 001101 // 13

B = 100101 // 37

A | B = 101101 // 45

3.位非

~A : 将a的二进制表示每一位进行取反操作,0变1,1变0.相当于相反数 - 1

A = 001101 // 13

~A = 11111111111111111111111111110010 // int32位,补码表示,位为符号位

// 根据上诉补码转原码为

// 10000000000000000000000000001110 // -14

4.左移操作

A << B:将A的二进制表示的每一位向左移B位, 左边超出的位截掉,右边不足的位补0。在取值范围内,移动一位相当于乘2.

A = 001101 // 13

A << 1 = 011010 // 26

三、实战操作

测试结果:

小明交了语文作业:3

小明又交了物理作业:19

小明还交了历史作业:147

小明撤销了历史作业:19

小明是否交了语文作业:true

小明是否交了历史作业:false

小明是否交了生物作业:false

小明是否交了全部作业:false

四、完美小结

内存由字节组成.每个字节由8位bit组成,每个bit状态只能是0或1.

所谓位模式,无非就是变量所占用内存的所有bit的状态的序列

运用场景:

订单实体,我们可能涉及到的状态有,是否发货,是否审核,是否付款,是否接受等等.

棋-牌游戏用户状态

棋盘的位图(棋盘模式)位置(域):上下左右 左上角 右上角 左下角 右下角 方位等待

用户是否提交多项认证资料等

优势:

占用内存少

具有高效的拷贝、设值、比较运算等

位并行运算的可能

不足:

难于调试

访问单独位的复杂性,易出错

难于扩展

不符合面向对象的风格

不能处理所有的任务;需要大量的工作

来源:掘金 链接:https://juejin.im/post/5d861a3ff265da03925a82d8


分享好友

分享这个小栈给你的朋友们,一起进步吧。

龍门客栈
创建时间:2019-01-12 10:22:35
来新手村升级打怪啊!
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • 栈栈
    栈主
  • gaokeke123
    嘉宾
  • ?
    嘉宾
  • 飘絮絮絮丶
    嘉宾

小栈成员

查看更多
  • 一号管理员
  • phyllis666
  • cynthia
  • 老七
戳我,来吐槽~