使用临时变量实现数据交换,代码如下:
int a = 1,b = 2, temp = a;
temp = a;
a = b;
b = temp;
System.out.println("a = " + a + ", b = " + b); // a = 2, b = 1
使用位运算实现数据交换,代码如下:
int a = 1,b = 2;
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println("a = " + a + ", b = " + b); // a = 2, b = 1
看到这种位运算,一般大脑就会觉得高级,会觉得效率应该也比较高吧,其实并不然,实验如下:
private static void switchData(int[] bytes) {
int temp;
for (int i = 0; i < bytes.length; i+=2) {
temp = bytes[i];
bytes[i] = bytes[i + 1];
bytes[i + 1] = temp;
}
}
如上方法,功能为:依次从bytes数组中取出两位数据进行交换。下面我们实例对应的位运算方法:
private static void switchData(int[] bytes) {
for (int i = 0; i < bytes.length; i+=2) {
bytes[i] = bytes[i] ^ bytes[i + 1];
bytes[i + 1] = bytes[i] ^ bytes[i + 1];
bytes[i] = bytes[i] ^ bytes[i + 1];
}
}
下面,我们定义一个比较大的数组对象,然后执行10次交换,并打印出每一次交换时使用的时间:
public static void main(String[] args) {
int[] bytes = new int[10000_0000];
for (int i = 0; i < 10; i++) {
long start = System.currentTimeMillis();
switchData(bytes);
System.out.println("使用时间:" + (System.currentTimeMillis() - start));
}
}
使用临时变量实现交换时,基本上使用时间为50毫秒上下,而使用位运算实现的交换时,使用时间差不多要70毫秒,这差距可是非常大的。
为什么我会想到这个问题,因为在做项目开发的时候,有一个应用使用到了摄像头,需要开启视频,Android手机摄像头传出的视频是很大的,需要压缩。Android摄像头传出的图片数据为原始数据(NV21格式),需要压缩为H264格式,而压缩为H264时,接收的参数为NV12数据,这时就需要把NV21转换为NV12,这两种格式都是YUV格式,不同点在于U和V的位置是相反的,所以转换格式就是把U和V的格式交换一下即可。当我们视频分辨率为1920 x 1080时,一张图片的大小为:byte[] onePicture = new byte[1920 x 1080 x 3 / 2],数据量相当的大,所以此时的数据交互如果用位运算那可就亏大发了,毫秒必争啊,为什么要争呢?因为要想不卡,视频需要1秒显示25张图片,1秒 / 25张 = 40毫秒,这就是说每张图片的处理时间如果在40毫秒以内就不会卡,假设你转换1张图片格式就花了40毫秒了,那你转换为格式还需要压缩呢,压缩完还要发送呢,这些都需要时间的,加起来就超过40毫秒了,那视频肯定就卡了,所以分秒必争啊这种情况。
那位运算的数据交换用在什么地方呢?用在那种内存很小,而且需要交换数据,并且交换次数并不多的场景。这种场景一般我们遇不到。