Java位運算子

J_W發表於2018-12-07

常見的運算子:

& 與

兩個數都轉為二進位制,然後從高位開始比較,如果兩個數都為1則為1,否則為0。

或(|)

兩個數只要有一個為1則為1,否則就為0。

非(~),反義詞

如果位為0,結果是1,如果位為1,結果是0

異或 (^)

相同為0,不相同則為1

說明:以上運算子均為位運算子,計算機中儲存的時數字的補碼,正數的補碼為本身,負數的補碼是:符號位不變,其他取反加一。

左移運算子<<

  • 規則:

    按二進位制形式把所有的數字向左移動對應的位數,高位移出(捨棄),低位的空位補零。

  當左移的運算數是int 型別時,每移動1位它的第31位就要被移出並且丟棄;

  當左移的運算數是long 型別時,每移動1位它的第63位就要被移出並且丟棄。

  當左移的運算數是byte 和short型別時,將自動把這些型別擴大為 int 型。

  • 數學意義:

    在數字沒有溢位的前提下,對於正數和負數,左移一位都相當於乘以2的1次方,左移n位就相當於乘以2的n次方。 3 << 2,其實就是3*2的二次方

右移運算子(>>)

  • 規則:

    按二進位制形式把所有的數字向右移動對應的位數,低位移出(捨棄),高位的空位補符號位,即正數補零,負數補1   當右移的運算數是byte 和short型別時,將自動把這些型別擴大為 int 型。

  例如,如果要移走的值為負數,每一次右移都在左邊補1,如果要移走的值為正數,每一次右移都在左邊補0,這叫做符號位擴充套件 (保留符號位)(sign extension ),在進行右移

  操作時用來保持負數的符號。

  • 數學意義:除2

無符號右移(>>>)

直接在高位補0,低位刪除。

        int i=-7;
        System.out.println(Integer.toBinaryString(i));
        System.out.println(Integer.toBinaryString(i>>>2));
        System.out.println(Integer.toBinaryString(i>>2));
        
        執行結果:
        11111111111111111111111111111001
        111111111111111111111111111110
        11111111111111111111111111111110
複製程式碼

從以上執行結果可以看出>>> 和>>的區別

例子:

hashmap原始碼中,計算key的hashcode方法如下

/**
     * Computes key.hashCode() and spreads (XORs) higher bits of hash
     * to lower.  Because the table uses power-of-two masking, sets of
     * hashes that vary only in bits above the current mask will
     * always collide. (Among known examples are sets of Float keys
     * holding consecutive whole numbers in small tables.)  So we
     * apply a transform that spreads the impact of higher bits
     * downward. There is a tradeoff between speed, utility, and
     * quality of bit-spreading. Because many common sets of hashes
     * are already reasonably distributed (so don't benefit from
     * spreading), and because we use trees to handle large sets of
     * collisions in bins, we just XOR some shifted bits in the
     * cheapest possible way to reduce systematic lossage, as well as
     * to incorporate impact of the highest bits that would otherwise
     * never be used in index calculations because of table bounds.
     */
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
複製程式碼

key的hashcode無符號右移了16位,然後與key的hashcode異或位運算。這種方法高效的讓hashcode的高位和低位進行了一次異或運算。據說可以產生更加隨機的hashcode,但是我並看不出來為什麼,如果有大神做過測試或者知道其中的原理可以留言。 但是可以知道的是,這種運算子在原始碼中很實用。

相關文章