平易な英語でのBitSetを説明します
原則
たBitSetは、より多くのように、動作のターゲット、0又はのみ偽と真1は、長尺の内部配列を維持する、すなわち値、最初だけ長いのでたBitSet最小サイズが64であった場合、記憶素子、内部たBitSetこれらの操作は透明であるため、動的拡張は、最終的に内部、N長いによって格納されます。
データが発生したかどうかを示すための1で、0があった、1が登場しました。この数が出現した場合、0のように表現するかどうかに応じていずれかと共に使用した場合。
1Gは,. 8空間である1024 1024 1024 = 8.58 10 ^ 9ビット、すなわち異なる数85億を表すことができます。
注意:ケースでのBitSetが安全ではありません動作する複数のスレッドの外部同期はありません。
例
例えば、数字の束を格納する必要があり、ソース= [3,5,6,9]
4 * INTは4つのバイトを必要と。
java.util.BitSetは真/偽保存することができます。
java.util.BitSetは、はるかに少ないであろう場合、原理は、
図1に示すように、最初のデータの最大値を見つける9 = MAXVALUE。
2、たBitSetのBSを宣言し、そのサイズは、10 = 1 + MAXVALUEである
3、データソースを介し。 。、BS [源[I] ]がtrueに設定されている
最後の値である:
(0 = FALSE; 1が真)
BS [0,0,0,1,0,1,1,0,0,1]
。3、 5,6、9
intは今、32ビットのデジタルの4バイトのみを占有入力する必要がありますように!
32:1の比率
ので、多くのスペースを節約するには
、通常、統計、分析の分野で使用されています。
初期化ロジック
次のように長い要素のデフォルトサイズに初期化され、ロジックは次のとおりです。
private final static int ADDRESS_BITS_PER_WORD = 6;
private final static int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD;
//用来开辟bit位空间
private long[] words;
//当前long数组的大小
private transient int wordsInUse = 0;
public BitSet() {
initWords(BITS_PER_WORD);
sizeIsSticky = false;
}
private void initWords(int nbits) {
words = new long[wordIndex(nbits-1) + 1];
}
//bitIndex除去64(bitIndex >> 6 )得到会落到long数组的index;
private static int wordIndex(int bitIndex) {
return bitIndex >> ADDRESS_BITS_PER_WORD;
}
基本操作のBitSet
public class BitUtils {
/**
* 获取运算数指定位置的值<br>
* 例如: 0000 1011 获取其第 0 位的值为 1, 第 2 位 的值为 0<br>
*
* @param source
* 需要运算的数
* @param pos
* 指定位置 (0<=pos<=7)
* @return 指定位置的值(0 or 1)
*/
public static byte getBitValue(byte source, int pos) {
return (byte) ((source >> pos) & 1);
}
/**
* 将运算数指定位置的值置为指定值<br>
* 例: 0000 1011 需要更新为 0000 1111, 即第 2 位的值需要置为 1<br>
*
* @param source
* 需要运算的数
* @param pos
* 指定位置 (0<=pos<=7)
* @param value
* 只能取值为 0, 或 1, 所有大于0的值作为1处理, 所有小于0的值作为0处理
*
* @return 运算后的结果数
*/
public static byte setBitValue(byte source, int pos, byte value) {
byte mask = (byte) (1 << pos);
if (value > 0) {
source |= mask;
} else {
source &= (~mask);
}
return source;
}
/**
* 将运算数指定位置取反值<br>
* 例: 0000 1011 指定第 3 位取反, 结果为 0000 0011; 指定第2位取反, 结果为 0000 1111<br>
*
* @param source
*
* @param pos
* 指定位置 (0<=pos<=7)
*
* @return 运算后的结果数
*/
public static byte reverseBitValue(byte source, int pos) {
byte mask = (byte) (1 << pos);
return (byte) (source ^ mask);
}
/**
* 检查运算数的指定位置是否为1<br>
*
* @param source
* 需要运算的数
* @param pos
* 指定位置 (0<=pos<=7)
* @return true 表示指定位置值为1, false 表示指定位置值为 0
*/
public static boolean checkBitValue(byte source, int pos) {
source = (byte) (source >>> pos);
return (source & 1) == 1;
}
/**
* 入口函数做测试<br>
*
* @param args
*/
public static void main(String[] args) {
// 取十进制 11 (二级制 0000 1011) 为例子
byte source = 11;
// 取第2位值并输出, 结果应为 0000 1011
for (byte i = 7; i >= 0; i--) {
System.out.printf("%d ", getBitValue(source, i));
}
// 将第6位置为1并输出 , 结果为 75 (0100 1011)
System.out.println("\n" + setBitValue(source, 6, (byte) 1));
// 将第6位取反并输出, 结果应为75(0100 1011)
System.out.println(reverseBitValue(source, 6));
// 检查第6位是否为1,结果应为false
System.out.println(checkBitValue(source, 6));
// 输出为1的位, 结果应为 0 1 3
for (byte i = 0; i < 8; i++) {
if (checkBitValue(source, i)) {
System.out.printf("%d ", i);
}
}
}
}
なぜint型ではない、長いでしょうか?
アレイの全てを横断する必要性を実装する場合JDKは、ロングたBitSet構造は、パフォーマンス上の理由のためであるように、あるいはたBitSetこの操作及び提供、または実行する必要があるので、内部ストレージアレイを選択し、すべてのビットまたはたBitSetの2ビット要素。それは内部ストレージ構造のBitSetの長い配列としてのJavaを使用することを選択したので、最小限に長いサイクル時間を利用することができます。
スタック上に保存されたデータから、バイト長の使用と実質的に違いはありません、7バイト(アドレスは8の倍数で行うためにそれらを強制する)までのバイトの廃棄物を使用した場合、コンパイラ軍アドレスアライメント、除きますアセンブリ命令異なる長さのmov命令データがあるので、グループを読み出す際、メモリ素子から加えて、差は、存在しません。だから、JDK根本原因の長いのBitSet構造として内部ストレージアレイを使用することを選択したサイクル数と時間を削減し、パフォーマンスを向上させることです。