位運算實現數據交換你以爲效率很高嗎?

使用臨時變量實現數據交換,代碼如下:

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毫秒了,那視頻肯定就卡了,所以分秒必爭啊這種情況。

那位運算的數據交換用在什麼地方呢?用在那種內存很小,而且需要交換數據,並且交換次數並不多的場景。這種場景一般我們遇不到。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章