💡 有一天,忽然來了一個需求,問小明提交了哪些課程的做業?java
這麼多課程.....我要8個字段? 萬一還有課程呢?我還要再加字段?bash
我確定不慌啊,我一個字段搞定。工具
經過一個 int
或者long
字段,來添加多個 標誌或者狀態. 一個int
或者long
字段,可以管理多個標記(狀態)值. 如此神奇的操做怎樣實現的呢? 答案就是經過位運算來實現.測試
像這種,獨立狀態(標記)之間相互組合能夠產生新的狀態(標記),且每一個獨立狀態(標記)只有true或者false值的,咱們可使用位狀態的概念來管理這些狀態.spa
它的核心思想就是將, int 數值看作是 二進制數位表示.若是有四個狀態就能夠像這樣 0000,用四位二進制表示,每個二進制位均可以表示一種狀態. 而後經過 位運算,來提取或添加標記位.四位對應的組合狀態有16個. 而咱們,只須要經過一個int變量就可以管理這些狀態.3d
當參與的狀態(標記)越多時,若是使用單獨的標記變量,就須要生成越多的變量,而用位域,這種獨立狀態爲無論有多少個,均可以用一個變量表示.int類型最多存放32個獨立狀態.調試
位操做基礎:code
java中提供的基礎位運算符有 與(&)
,或(|)
,非(~)
,異或(^)
,左移<<
,右移(>>)
和無符號右移(>>>)
.cdn
除了位非(~)
是一元操做符外,其它的都是二元操做符。對象
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
複製代碼
/** * @author LiJing * @ClassName: BitStatusUtils * @Description: 位運算處理狀態的工具類 * @date 2019/9/21 * @time 10:38 */
public class BitStatusUtils {
//A:語文 B:數學 C:英語 D:物理 E:化學 F:生物 G:歷史 H:地理
// 二進制表示 0001 沒有交任何做業
public static final int NONE = 1<<0; //默認
public static final int CHINESE = NONE<<1;//語文
public static final int MATH = NONE<<2;//數學
public static final int ENGLISH = NONE<<3;//英語
public static final int PHYSICS = NONE<<4;//物理
public static final int CHEMISTRY = NONE<<5;//化學
public static final int BIOLOGY = NONE<<6;//生物
public static final int HISTORY = NONE<<7;//歷史
public static final int GEOGRAPHY = NONE<<8;//地理
public static final int ALL =NONE|CHINESE|MATH|ENGLISH|PHYSICS|CHEMISTRY|BIOLOGY|HISTORY|GEOGRAPHY;
/** * @param status 全部狀態值 * @param value 須要判斷狀態值 * @return 是否存在 */
public static boolean hasStatus(long status, long value) {
return (status & value) != 0;
}
/** * @param status 已有狀態值 * @param value 須要添加狀態值 * @return 新的狀態值 */
public static long addStatus(long status, long value) {
if (hasStatus(status, value)) {
return status;
}
return (status | value);
}
/** * @param status 已有狀態值 * @param value 須要刪除狀態值 * @return 新的狀態值 */
public static long removeStatus(long status, long value) {
if (!hasStatus(status, value)) {
return status;
}
return status ^ value;
}
/**是否交了含有所有狀態 * @param status * @return */
public static boolean hasAllStatus(long status) {
return (status & ALL) == ALL;
}
public static void main(String[] args) {
long status = addStatus(NONE, CHINESE);
System.out.println("小明交了語文做業:" + status);
status = addStatus(status, PHYSICS);
System.out.println("小明又交了物理做業:" + status);
status = addStatus(status, HISTORY);
System.out.println("小明還交了歷史做業:" + status);
status = removeStatus(status, HISTORY);
System.out.println("小明撤銷了歷史做業:" + status);
System.out.println("小明是否交了語文做業:" + hasStatus(status, CHINESE));
System.out.println("小明是否交了歷史做業:" + hasStatus(status, HISTORY));
System.out.println("小明是否交了生物做業:" + hasStatus(status, BIOLOGY));
System.out.println("小明是否交了所有做業:" + hasAllStatus(status));
}
}
複製代碼
測試結果:
小明交了語文做業:3
小明又交了物理做業:19
小明還交了歷史做業:147
小明撤銷了歷史做業:19
小明是否交了語文做業:true
小明是否交了歷史做業:false
小明是否交了生物做業:false
小明是否交了所有做業:false
複製代碼
內存由字節組成.每一個字節由8位bit組成,每一個bit狀態只能是0或1.
所謂位模式,無非就是變量所佔用內存的全部bit的狀態的序列
運用場景:
優點:
不足: