大家好,我是北军。在本文中,我们将了解如何使用按位运算符实现低级位掩码。我们将看到如何将单个int变量作为单个数据容器。位掩码位掩码允许我们在一个数值变量中存储多个值。我们没有将此变量视为整数,而是将其每个位视为一个单独的值。因为一位可以等于0或1,所以我们也可以认为它是假的或真的。我们还可以将一组位切片,并将它们视为更小的数值变量甚至字符串。举个例子,假设我们有一个最小内存空间,需要将所有关于用户帐户的信息存储在一个int变量中。前八位(来自32个可用位)将存储布尔信息,例如“此帐户是否有效?”或者“这个账户是溢价吗?”至于剩下的24位,我们将它们转换成三个字符,作为.net的用户标识。编码我们的用户将有一个标识符“AAA”,他将有一个活跃的高级帐户(存储在前两位)。在二进制表示中它看起来像。字符串stringRepresentation="01000001010000010100000100000011";这可以使用内置的Integer#parseUnsignedInt方法轻松编码为int变量。intintRepresentation=Integer.parseUnsignedInt(stringRepresentation,2);assertEquals(intRepresentation,1094795523);也可以使用Integer#toBinaryString方法反转解码过程。字符串binaryString=Integer.toBinaryString(intRepresentation);StringstringRepresentation=padWithZeros(binaryString);assertEquals(stringRepresentation,"01000001010000010100000100000011");提取位Firstbit如果我们想检查帐户变量的第一位,我们只需要使用序列按位与运算符和数字1作为掩码。由于数字1在二进制形式中只有第一位设置为1,其余位均为0,因此它将从我们的变量中删除所有位,只留下第一个完整位。100000101000001010000010000000110000000000000000000000000000001--------------------------------&0000000000000000000000000000000000000000等于零。intRepresentation&1!=0bitatanyposition如果我们想检查其他位,我们需要创建一个适当的掩码,要求在给定位置将一个位设置为1,其余位设置为0。最简单的方法就是改变我们已有的面具。1<<(position-1)在上面的代码行中将位置变量设置为3会将我们的掩码从0000000000000000000000000000001更改为000000000000000000000000000000100现在,位方程将如下所示。1000001010000010100000100000001100000000000000000000000000000100--------------------------------&00000000000000000000000000000000000把所有的方法都写成a000,在位置中提取给定的单个位。privatebooleanextractValueAtPosition(intintRepresentation,intposition){return((intRepresentation)&(1<<(position-1)))!=0;}为了达到同样的效果,我们也可以将intRepresentation变量往反方向移动,而不是改变面具。提取多位我们可以用类似的方式从一个整数中提取多位。让我们提取用户帐户变量的最后三个字节并将其转换为字符串。首先,我们需要通过将变量右移来去掉前八位。intlastThreeBites=intRepresentation>>8;StringstringRepresentation=getStringRepresentation(lastThreeBites);assertEquals(stringRepresentation,"00000000010000010100000101000001");我们仍然有32位,因为int总是有32位。然而,现在我们只对前24位感兴趣,其余的都是零,很容易被忽略。我们创建的int变量可以很容易地用作整数ID,但由于我们想要一个字符串ID,我们还需要执行一个步骤。我们将二进制字符串表示拆分为8个字符的组,将它们解析为char变量,并将它们连接成最终的字符串。为方便起见,我们还将省略空字节。Arrays.stream(stringRepresentation.split("(?<=\\G.{8})")).filter(eightBits->!eightBits.equals("00000000")).map(eightBits->(char)Integer.parseInt(eightBits,2)).collect(StringBuilder::new,StringBuilder::append,StringBuilder::append).toString();应用位掩码我们还可以创建一个掩码来一次检查许多位,而不是提取和检查单个位的值。我们想检查我们的用户是否有一个活跃的高级帐户,所以他的变量的前两位都设置为1。我们可以像以前一样单独检查它们,但是创建一个掩码来选择它们会更快。intuser=Integer.parseUnsignedInt("00000000010000010100000101000001",2);intmask=Integer.parseUnsignedInt("0000000000000000000000000000011",2);,因此屏蔽值只会将第一位设置为1。assertEquals(getStringRepresentation(masked),"000000000000000000000000000000001");现在我们可以轻松且廉价地断言用户是否符合我们的标准。assertFalse((用户&掩码)==掩码);总结在本教程中,我们学习了如何使用位运算符创建位掩码并应用它们从整数中提取二进制信息。
