提取信息,Java還有這個操作!你明白了嗎?
大家好,我是指北君。
在本文中,我們來看看如何使用位操作符實現(xiàn)低級別的位掩碼。我們將看到我們?nèi)绾螌⒁粋€單一的int變量作為一個單獨的數(shù)據(jù)容器。
位掩碼
位掩碼允許我們在一個數(shù)字變量中存儲多個值。我們不再把這個變量看作一個整數(shù),而是把它的每一個比特當(dāng)作一個獨立的值。
因為一個比特可以等于 0 或 1,我們也可以把它看成是 false 或 true 。我們也可以把一組比特切開,把它們當(dāng)作一個較小的數(shù)字變量甚至是一個String。
舉個例子
假設(shè)我們有一個最小的內(nèi)存空間,并且需要在一個int變量中存儲所有關(guān)于用戶賬戶的信息。前八位(來自32個可用位)將存儲boolean信息,如 "該賬戶是否激活?"或 "該賬戶是否溢價?"
至于剩下的24位,我們將把它們轉(zhuǎn)換成三個字符,作為用戶的標(biāo)識符。
編碼
我們的用戶將有一個標(biāo)識符 "AAA",他將有一個活躍的高級賬戶(存儲在前兩個比特)。在二進(jìn)制表示中,它將看起來像。
使用內(nèi)置的Integer#parseUnsignedInt方法,可以很容易地將其編碼為一個int變量。
解碼
這個過程也可以用 Integer#toBinaryString 方法來反轉(zhuǎn)。
提取一個比特
第一比特
如果我們想檢查我們賬戶變量的第一位,我們只需要使用順位 and 運算符和數(shù)字 1 作為掩碼。因為數(shù)字 1在二進(jìn)制形式中只有第一位被設(shè)置為1,其余的都是0,它將從我們的變量中刪除所有的位,只留下第一個完整的位。
然后我們需要檢查產(chǎn)生的值是否不等于零。
任意位置的位
如果我們想檢查其他的位,我們需要創(chuàng)建一個適當(dāng)?shù)难诖a,這個掩碼需要在給定的位置上有一個位設(shè)置為1,其余的設(shè)置為0。最簡單的方法是對我們已有的掩碼進(jìn)行移位。
上面這行代碼的位置變量設(shè)置為3,將把我們的掩碼從 00000000000000000000000000000001 變成
因此,現(xiàn)在,比特方程將看起來像這樣。
把所有這些放在一起,我們可以寫一個方法來提取給定位置上的單個比特。
為了達(dá)到同樣的效果,我們也可以將intRepresentation變量向相反方向移動,而不是改變掩碼。
提取多個比特
我們可以用類似的方法從一個整數(shù)中提取多個比特。讓我們提取我們的用戶帳戶變量的最后三個字節(jié),并將其轉(zhuǎn)換為一個字符串。首先,我們需要通過將變量向右移動來擺脫前八位的影響。
我們?nèi)匀挥?2位,因為int總是有32位。然而,現(xiàn)在我們只對前24位感興趣,其余的都是零,會很容易被忽略。我們創(chuàng)建的int變量可以很容易地用作整數(shù)ID,但是因為我們想有一個字符串ID,所以我們還有一個步驟要做。
我們將把二進(jìn)制的字符串表示法分成8個字符的組,把它們解析成char變量,然后把它們連接成一個最終的String。
為了方便起見,我們還將忽略空字節(jié)。
應(yīng)用一個比特掩碼
我們也可以創(chuàng)建一個掩碼來同時檢查許多位,而不是提取和檢查單個位的值。我們想檢查我們的用戶是否有一個活躍的高級賬戶,所以他的變量的前兩個比特都設(shè)置為1。
我們可以用以前的方法分別檢查它們,但創(chuàng)建一個掩碼來選擇它們,會更快。
因為我們的用戶有一個活躍的賬戶,但它不是高級賬戶,所以被屏蔽的值將只有第一個比特被設(shè)置為1。
現(xiàn)在,我們可以輕松而廉價地斷言一個用戶是否符合我們的條件。
總結(jié)
在本教程中,我們學(xué)習(xí)了如何使用位運算符來創(chuàng)建位掩碼,并應(yīng)用它們來從整數(shù)中提取二進(jìn)制信息。