JAVA位运算应用
一、位运算符区别
>>:逻辑右移 正数补0,负数补1,不改变正副
>>>:算术右移:高位补0,改变正副
<<:逻辑左移 最后一位是0补0,是1补1
二、数据类型转化为字节数组
无论是什么数据类型,在计算机中都以二进制形式存在。比如int类型,由四字节组成,通过一系列的位运算,可以获取他的某一位,放入字节数组中。
当前要转换的int类型的数为:
A8 2B 7A 4F
二进制表示: 00111000 00101011 01111010 01001111
当要取得每个字节时:只需要和11111111进行相与即可
如果要得到4F:
10101000 00101011 01111010 01001111
00000000 00000000 00000000 11111111
如果要得到7A:这个数右移8个单位
00000000 10101000 00101011 01111010
00000000 00000000 00000000 11111111
依次类推
我们可以发现,获取从低位到高位的字节时,需要转换的值都需要向右进行移动,且是算数右移
public static byte[] getBytes(int value) {
byte[] res = new byte[4];
for (int i = 0; i < res.length; i++) {
res[i] = (byte)((value >>> (i<<3)) & 0xFF);
}
return res;
}
三、字节数组转换为基础数据类型
还是之前的那个例子
将这串二进制转换为int类型
10101000 00101011 01111010 01001111
这里我们从高位开始,每次i和高位进行按位与,后面一步一步的向前移动,我们需要注意的是,当一个字节进行自动类型转换的时候,会根据高位的数字进行补齐。那么10101000会变为
11111111 11111111 11111111 10101000
| 00000000 00000000 00000000 00000000
结果为 11111111 11111111 11111111 10101000
这种结果是我们不希望看见的,所以在相或之前,应该和0xFF进行按位与
11111111 11111111 11111111 10101000
& 00000000 00000000 00000000 11111111
00000000 00000000 00000000 10101000
之后结果向左进行移位,和倒数第二个字节数进行相或
00000000 00000000 10101000 00000000
| 00000000 00000000 00000000 00101011
00000000 00000000 10101000 00101011
依次类推,就得到了真正的int数值
字节数组中高位应该先赋值给int类型中的低字节,再通过将int左移操作将其一步步挪到高位上。
当取出字节数组中的一个元素并将其和int按位或时,该8位二进制会被自动补全为4*8=32位二进制,而补的是符号位,固需要考虑符号位为1时,防止数据出错,固需要额外一步和0xFF按位与,只取出最低位即可。
public static int bytesToInt(Byte[] bytes) {
int res = 0;
for (int i = 0; i < 4; i++) {
res <<= 8;
res |= (bytes[4 - i - 1] & 0xFF);
}
return res;
}
四、数据类型和字节数组的相互转换的代码
/**
* @Author :漠殇
* @Data :Create in 11:41 2021/8/4
*/
public class BytesTransfer {
private static final int SHORT_BYTE_COUNT = 2;
private static final int INT_BYTE_COUNT = 4;
private static final int LONG_BYTE_COUNT = 8;
public BytesTransfer() {
}
/**
* 将int类型数据转换为字节数组
* @param value 需要转换的int类型数据
* @return 该数据转换的字节数组
*/
public static byte[] toBytes(int value) {
byte[] res = new byte[INT_BYTE_COUNT];
for (int i = 0; i < res.length; i++) {
res[i] = (byte) ((value >>> (i << 3)) & 0xFF);
}
return res;
}
/**
* 将int型数据转换成二进制,加到数组 {@code bytes}
* 中从 {@code offset} 开始的地方
*
* @param value 需要转换的int型数据
* @return 添加数据后的二进制数组
*/
public static byte[] toBytes(int value, long offset, byte[] bytes) {
for (int i = 0; i < 4; i++) {
bytes[i + offset] = (byte) ((value >>> (i << 3)) & 0xFF);
}
return bytes;
}
/**
* 将字节数组转化为int类型的数据
* @param bytes 需要转换的字节数组
* @return 转换的int类型 的值
*/
public static int bytesToInt(byte[] bytes) {
if (bytes.length != BytesTransfer.INT_BYTE_COUNT) {
throw new InvalidBytesNumberException("bytes length [" +
bytes.length + "] is not 4, can't transfer to [int].");
}
int res = 0;
for (int i = 0; i < 4; i++) {
res <<= 8;
res |= (bytes[4 - i - 1] & 0xFF);
}
return res;
}
/**
* 将二进制数组 {@code bytes} 从 {@code offset} 起后四位,
* 放到一个临时字节数组中,然后调用 bytesToInt(byte[] bytes)转换
*
* @param bytes 需要转换的二进制数组
* @param offset 起始下标偏移量
* @return 转换的 int型 值
*/
public static int bytesToInt(byte[] bytes, long offset) {
if (bytes.length - offset < BytesTransfer.INT_BYTE_COUNT) {
throw new InvalidBytesNumberException("bytes rest length [" +
(bytes.length - offset) + "] is less than 4, can't transfer to [int].");
}
byte[] tmp = new byte[4];
for (int i = 0; i < 4; i++) {
tmp[i] = bytes[offset + i];
}
return bytesToInt(tmp);
}
/**
* 将long类型数据转换为字节数组
* @param value 需要转换的long类型数据
* @return 该数据转换的字节数组
*/
public static byte[] toBytes(long value) {
byte[] res = new byte[LONG_BYTE_COUNT];
for (int i = 0; i < res.length; i++) {
res[i] = (byte) ((value >>> (i << 3)) & 0xFF);
}
return res;
}
/**
* 将long型数据转换成二进制,加到数组 {@code bytes}
* 中从 {@code offset} 开始的地方
*
* @param value 需要转换的long型数据
* @return 添加数据后的二进制数组
*/
public static byte[] toBytes(long value, long offset, byte[] bytes) {
for (int i = 0; i < 8; i++) {
bytes[i + offset] = (byte) ((value >>> (i << 3)) & 0xFF);
}
return bytes;
}
/**
* 将字节数组转化为long类型的数据
* @param bytes 需要转换的字节数组
* @return 转换的long类型 的值
*/
public static long bytesToLong(byte[] bytes) {
if (bytes.length != BytesTransfer.LONG_BYTE_COUNT) {
throw new InvalidBytesNumberException("bytes length [" +
bytes.length + "] is not 8, can't transfer to [long].");
}
long res = 0;
for (int i = 0; i < 8; i++) {
res <<= 8;
res |= (bytes[8 - i - 1] & 0xFF);
}
return res;
}
/**
* 将二进制数组 {@code bytes} 从 {@code offset} 起后八位,
* 放到一个临时字节数组中,然后调用 bytesToInt(byte[] bytes)转换
*
* @param bytes 需要转换的二进制数组
* @param offset 起始下标偏移量
* @return 转换的 long型 值
*/
public static long bytesToLong(byte[] bytes, long offset) {
if (bytes.length - offset < BytesTransfer.LONG_BYTE_COUNT) {
throw new InvalidBytesNumberException("bytes rest length [" +
(bytes.length - offset) + "] is less than 8, can't transfer to [long].");
}
byte[] tmp = new byte[8];
for (int i = 0; i < 8; i++) {
tmp[i] = bytes[offset + i];
}
return bytesToLong(tmp);
}
/**
* 将short类型数据转换为字节数组
* @param value 需要转换的short类型数据
* @return 该数据转换的字节数组
*/
public static byte[] toBytes(short value) {
byte[] res = new byte[SHORT_BYTE_COUNT];
for (int i = 0; i < res.length; i++) {
res[i] = (byte) ((value >>> (i << 3)) & 0xFF);
}
return res;
}
/**
* 将short型数据转换成二进制,加到数组 {@code bytes}
* 中从 {@code offset} 开始的地方
*
* @param value 需要转换的long型数据
* @return 添加数据后的二进制数组
*/
public static byte[] toBytes(short value, short offset, byte[] bytes) {
for (int i = 0; i < 2; i++) {
bytes[i + offset] = (byte) ((value >>> (i << 3)) & 0xFF);
}
return bytes;
}
/**
* 将字节数组转化为short类型的数据
* @param bytes 需要转换的字节数组
* @return 转换的short类型 的值
*/
public static short bytesToShort(byte[] bytes) {
if (bytes.length != BytesTransfer.SHORT_BYTE_COUNT) {
throw new InvalidBytesNumberException("bytes length [" +
bytes.length + "] is not 2, can't transfer to [short].");
}
short res = 0;
for (int i = 0; i < 2; i++) {
res <<= 8;
res |= (bytes[2 - i - 1] & 0xFF);
}
return res;
}
/**
* 将二进制数组 {@code bytes} 从 {@code offset} 起后二位,
* 放到一个临时字节数组中,然后调用 bytesToInt(byte[] bytes)转换
*
* @param bytes 需要转换的二进制数组
* @param offset 起始下标偏移量
* @return 转换的 long型 值
*/
public static int bytesToShort(byte[] bytes, long offset) {
if (bytes.length - offset < BytesTransfer.SHORT_BYTE_COUNT) {
throw new InvalidBytesNumberException("bytes rest length [" +
(bytes.length - offset) + "] is less than 2, can't transfer to [short].");
}
byte[] tmp = new byte[2];
for (int i = 0; i < 2; i++) {
tmp[i] = bytes[offset + i];
}
return bytesToShort(tmp);
}
}