Javaプログラミング・ロジック(27) - 分析パッケージ(中)

このセクションでは、パッケージを調査し続けていない、同様のセクションの文字クラス、ロング整数の下で、Integerクラスを導入し、それはもはや別のプレゼンテーションで、その他の基本的なクラスを超える導入されている、それらを繰り返しません。

どのような簡単な整数は、それを導入するには?それはほかに、我々はまた、そののvalueOfが達成分析、我々は見て、いくつかのバイナリ事業を展開しています。

なぜ我々はそれを実装して、コードを気にする必要がありますか?ほとんどの場合、我々は、我々は主に、特にどこバイナリ操作、学ぶためにそれを使用することができるようになります、気にしない、バイナリコンピュータの基本ですが、コードは、多くの場合、我々はそれらをより持ちたい、不明瞭さ深い理解をクリアします。

ビットフリップで見てみましょう。

ビットフリップ

使い方

整数ビット反転することができる2つの静的メソッドがあります。

公共の静的なint型リバース(int型I)
のpublic static int型のreverseBytes(I int型)

ビットフリップはreverseBytesバイトによって交換可能であり、逆互換ビットは、バイナリ、左交換の右へのビットのビットとして整数です。例で見てみましょう:

コードをコピー
int型、A = 0x12345678の。
System.out.println(Integer.toBinaryString(a)参照)。

INT R = Integer.reverse()。
System.out.println(Integer.toBinaryString(登録商標)); 

INT RB = Integer.reverseBytes()。
System.out.println(Integer.toHexString(RB))。
コードをコピー

 整数であり、第一出力される割り当て進、バイナリストリングは、次いで逆は出力として、バイナリ、進reverseBytes最終的な出力を出力します。

10010001101000101011001111000 
11110011010100010110001001000 
78563412

reverseBytesはバイト、78バイトの16進表現を反転され、それは12であるので、結果は理解し78563412容易です。

出力は32ではないので、一見バイナリフリップは、夜12時無視前の出力が間違っている、私たちは32ルックを満​​たしました:

00010010001101000101011001111000 
00011110011010100010110001001000

右の結果。

これらの2つの方法は、それを達成するためにどのようにしていますか?

reverseBytes

reverseBytesコードを見て:

コードをコピー
公共の静的なint型reverseBytes(INT I){ 
    リターン((I >>> 24))| 
           ((I >> 8)&は0xFF00)| 
           ((I << 8)&は0xFF0000)| 
           ((I << 24))。
}
コードをコピー

私は0x12345678のに等しいパラメータ、例えば、我々は、実装プロセスを分析します:

私は>>> 24符号なし右シフト、最上位バイトが最下位ビットに移動し、結果は0x00000012です。

第二のバイトの右側に予約されている(I >> 8)&は0xFF00は、第二、I >> 8結果0x00123456の右側にある2番目のバイトの左側に移動し、その後、&は0xFF00、結果は0x00003400です。

3バイト目の右側に予約されている(I << 8)&は0xFF0000、第左の2番目のバイトの右側に移動し、I << 8結果0x34567800は、その後、&は0xFF0000、結果は0x00560000です。

私<< 24は、結果は0x78000000で、ほとんどの左と右のほとんど動かさバイト。

その後、4つの結果や操作|バイトの目的を達成するために、結果はそう左、右で、0x78563412で、及びまたは動作は、逆転しました。

私たちは、逆のコードを見て:

コードをコピー
公共の静的なint型リバース(int型はI){ 
    // HD、図7-1は、
    | I(I&0x55555555)<< 1 = (I >>> 1)&0x55555555。
    |私は2 <<(I&0x33333333)= (I >>> 2)&0x33333333。
    I =(I&0x0f0f0f0f)<< 4 | (I >>> 4)&​​0x0f0f0f0f。
    私は、(i << 24)= | ((I&は0xFF00)<< 8)| 
        ((I >>> 8)&は0xFF00)| (I >>> 24)。
    私は返します。
}
コードをコピー

このコードは非常に短いですが、非常に不明瞭ものの、最終的にはそれが何を意味するのでしょうか?

最初の行はコメント、「HD、図7-1」、それはどういう意味ですか?HDは、ハッカーのディライト、HDの頭文字という本で表され、以下のように、図7-1は7-1本、書籍、コンテンツのための図です。

図から分かるように、逆のコードで整数ブック図7-1、図もショーで解釈コードのコードのコピーが、我々はそれを翻訳です。

2つ、4つのスイッチングのグループに続く隣接ビットのその後交換、8、16、16のグループのように、効率的な実装ビットフリップ、単一ビットスワップ隣接する第一、及びの基本的な考え方少し後に完了する。このアイデアは、だけでなく、2進数、10進数に適用されるの理解を容易にするために、も適用可能であるが、我々は、そのようなデジタルフリップ12345678 10進の例を、見て

最初のラウンド、隣接する単一のデジタル入れ替え、結果は次のとおりです。

21 43 65 87

第二ラウンド、隣接の交換には、2つの数字の組、結果は次のとおりです。

43 21 87 65

第三ラウンド、隣接の交換のための4つの数字のグループ、結果は次のとおりです。

8765 4321

フリップ完成。

小数のために、効率が高くないが、隣接するバイナリ・ビットの複数一つの命令で交換することができるので、バイナリのために、それが効率的です。

この行は、単一のインターチェンジに隣接しています:

X =(X&0x55555555)<< 1 | (X&0xAAAAAAAA)>>> 1。

5 0101,0x55555555バイナリバイナリ表現です。

01010101010101010101010101010101

X&0x55555555は、xの奇数番目のビットを取ることです。

バイナリは1010,0xAAAAAAAAバイナリ表現されています。

10101010101010101010101010101010

X&0xAAAAAAAAは​​、偶数ビットxをとっています。

(X&0x55555555)<< 1 | (X&0xAAAAAAAA)>>> 1。

Xを右に左に、偶数ビット、奇数ビットによって表され、その後|合併は、交換可能な隣接ビットの目的を達成します。このコードは小さなのみ定数0x55555555と最初のシフト操作の第2の半分を有するように最適化することができ、次のようになります。

(I&0x55555555)<< 1 | (I >>> 1)&0x55555555。

同様に、次のコードは、隣接ビットのグループ内の2ビットが交換可能です。

|私は2 <<(I&0x33333333)= (I&0xCCCCCCCC)>>> 2。

3 0011,0x33333333バイナリバイナリ表現です。

00110011001100110011001100110011 

X X&0x33333333は、セットの下半分のうちの2つを取ることです。

Cは1100,0xCCCCCCCCバイナリバイナリ表現です。

11001100110011001100110011001100

X X&0xCCCCCCCCは、セット上の2つの半分の高さに参加することです。

(I&0x33333333)<< 2 | (I&0xCCCCCCCC)>>> 2。

交換の目的を達成するため、合成| Xは2に設定し、変位の変位高い、高い、の下半分の下半分のように表されます。同様に、定数は0xCCCCCCCCを除去することができ、コードに対して最適化することができます。

(I&0x33333333)<< 2 | (I >>> 2)&0x33333333。

同様に、次のコードは、4ビットのグループに、交換されています。

I =(I&0x0f0f0f0f)<< 4 | (I >>> 4)&0x0f0f0f0f。

より直接的な形に従い、reverseBytes実質的に同一のコードとして単位を書き込むことができ、逆バイトであることを、オクテット単位で切り替えられます。

私は、(i << 24)= | ((I&は0xFF00)<< 8)| 
    ((I >>> 8)&は0xFF00)| (I >>> 24)。

なぜ逆のコードを書くので、それを覆い隠しますか?または書き込みは、それの方法を理解しやすくすることはできませんか?2つのExchangeの真ん中が完了するまで例えば、フリップ達成するために、一般的な考え方は、第二および最後から二番目のスワップ、最初と最後の交換です。データはバイナリビットでない場合は、アイデアは良いですが、ビットのために、効率が比較的低いです。

CPU命令及び効率的な動作が遅く単一ビット、典型的には32ビット動作(32ビットマシン)、また、CPUを効率的に実現することができるシフトおよび論理演算であるデータの最小単位が、数学することはできません。

これらの特性を逆にすると、隣接ビットのパラレルかつ効率的な交換で行わフルCPU使用率であり、同様の機能はまた、他の方法を理解するのが容易に達成することができ、これは困難なコードよりも効率的です。

巡回シフト

使い方

整数2つの静的メソッドを巡回シフトすることができますがあります。

rotateLeft int型のpublic static(int型I、int型の距離)
rotateRight int型のpublic static(int型I、int型の距離)

rotateLeftは左回転、rotateRightが回転右、距離のビットの数が移動している、いわゆるサイクリックシフトされる、シフトは、元の上位2つの、2左のような一般的なシフトの観点から一般に相対的ですそこに0を記入します権利はありません、それは2つのサイクルを左にシフトされている場合、元トップ2は、同じ連絡先の周りのリングのように、右端に移動します。例で見てみましょう:

コードをコピー
int型、A = 0x12345678の。
INT B = Integer.rotateLeft(8)。
System.out.println(Integer.toHexString(b)参照)。

INT C = Integer.rotateRight(8)。
System.out.println(Integer.toHexString(c)参照)
コードをコピー

Bの出力は、8ビットの円形の左シフトの結果は、cは8ビットの円形の右シフトが結果です。

34567812 
78123456

実装コード

コードを実装し、これら2つの関数は、次のとおりです。

コードをコピー
rotateLeft(int型I、int型の距離){int型のpublic static 
    リターン(I <<距離)| (I >>> -distance)。
} 
パブリックstatic int型rotateRight(INT I、INT距離){ 
    リターン(I >>>距離)| (I << -distance)。
}
コードをコピー

これらの2つの機能は、不可解されている距離が8であれば、私>>>という、負である - 8は、それが何を意味するのでしょうか?実際には、直接デジタルシフトの最小の実際の数はバックではなく、5のダイレクトデジタル値、またはデジタル&0x1Fのの直接の結果です。最大5がint整数が無効である31以上のペアをシフトする、31を表すためです。

負の意味を動かすの位置を理解し、我々は可能性が高い上記のコードには、例えば、-8バイナリ表現は次のようになります。

11111111111111111111111111111000

>>>私はその最低5は、小数点以下は24で、11000です - 私は>>> 24で8、I << 8 | I >>> 24は8左に回転させられます。

上記のコードは、私は>>> - 距離iは、<<(32-距離)である - の距離は、私は<<(32-距離)>>> Iです。

ビット単位の検索、カウント数

他のビットは、整数演算は、を含むがあります。

公共の静的なint型のシグナム(I int型)

符号ビットをチェックし、プラスのリターン1、-1、0、負の戻り0

lowestOneBit int型のpublic static(I int型)

不変のままで最初のものの位置番号から右を見つけ、他のビットが0に設定され、整数が戻されます。例えば、図3は、11バイナリ、バイナリ結果は01であり、小数点以下が1である、20、10100バイナリであり、結果は00100であり、4小数です。

highestOneBit int型のpublic static(int型I) 

不変のままで第1位置番号1の左側から見た、他のビットが0に設定され、整数が戻されます。

BITCOUNT int型のpublic static(I int型)  

数1のバイナリ表現を検索します。図20は、例えば、2進数2 10100,1あります。

公共の静的なint型のnumberOfLeadingZeros(I int型)

左側の始まりは、連続するゼロの数です。図20は、例えば、バイナリ27 0を左に、10100です。

公共の静的なint型のnumberOfTrailingZeros(I int型)

右端は連続した0の数です。図20は、例えば、バイナリ、右側に2つのゼロがあり、10100です。

コードの実現については、本書のハッカーのディライト関連する章を監督のコメントがあり、私はそれらを繰り返すことはしません。

実現のvalueOf

前節で述べたときは、ラッパークラスのオブジェクトを作成し、あなたが、あなたはまた、新しいダイレクトを使用することができ、静的valueOfメソッドを使用することができますが、のvalueOfを使用することをお勧めします、なぜですか?私たちは、のvalueOfコードを見て:

コードをコピー
パブリック静的整数のvalueOf(INT I){ 
    > = 127 IntegerCache.highアサート。
    (I> = IntegerCache.low && iが<= IntegerCache.high)場合
        IntegerCache.cache [I +(-IntegerCache.low)]を返します。
    新しい整数(i)を返します。
}
コードをコピー

それは次のようにプライベート静的クラスのコード内にあるIntegerCacheを、使用しています。

コードをコピー
プライベート静的クラスIntegerCache { 
    静的最終int型のロー= -128。
    静的最終int型の高。
    静的最終整数キャッシュ[]。

    静的{ 
        //高い値は、プロパティによって構成することができる
        = 127 INTの時間; 
        ストリングintegerCacheHighPropValue = 
            sun.misc.VM.getSavedProperty( "java.lang.Integer.IntegerCache.high")。
        (!integerCacheHighPropValue = null)の場合は{ 
            int型I =のparseInt(integerCacheHighPropValue)。
            私はMath.maxを=(I、127)。
            //最大のアレイサイズにInteger.MAX_VALUEある
            H = Math.min(Iは、Integer.MAX_VALUE - ( -低)-1)。
        } 
        高= H;

        キャッシュ=新しい整数〔(高-低)+ 1]。
        int型J =低いです。
        (; K <cache.length K ++のint K = 0)のための
            キャッシュ[K] =新しい整数(j ++); 
    } 

    プライベートIntegerCache(){} 
}
コードをコピー

キャッシュは、整数変数の静的配列は、デフォルトで、ブロック初期静的に初期化される、請求キャッシュを表すIntegerCache整数、ストレージ127、Integerオブジェクトに-128から整数に対応する256の合計。

valueOfコードで、値がIntegerCache、キャッシュのない範囲のみから直接作成された事前取得Integerオブジェクトは、オブジェクトが新規で作成されていないデフォルトである127 -128のキャッシュの範囲内にある場合。

一般的なオブジェクトを共有することにより、あなたは、メモリ空間を節約することができ整数は不変であるから、オブジェクトを安全に共有することができるキャッシュされています。ブール/バイト/ショート/ロング/キャラクターは、同様の実装があります。思考のこの共有共通オブジェクト、共通の設計思想である、<デザインモード>この作品では、それは英語フライ級、軽量の要素、すなわちシェアと呼ばれるフライ級と呼ばれる名前を、与えられています。

概要

このセクションでは、整数、オペレーションコードで動作し、いくつかのビットがより曖昧ビットが、パフォーマンスが比較的高い、我々は詳細にあなたがより多くの程度を知りたい場合は、いくつかのコードを説明する説明、コメントによると、この本のハッカーの喜びを参照してください。我々はまた、実現のvalueOfを導入し、Flyweightパターンを紹介します。

次のセクションでは、私たちが文字を探検しましょう

おすすめ

転載: www.cnblogs.com/ivy-xu/p/12584571.html