BitSet与EnumSet的根本使用
BitSet与EnumSet的基本使用
如果要高效率的存贮大量开关信息,BitSet是很好的选择,不过它的效率是针对空间而言的;如果需要高效的访问时间,BitSet比本地数组稍慢一些。BitSet的最小容量是64位,如果存储的内容比较小,如8位。那么BitSet就浪费了一些空间。BitSet会随着元素的加入而扩充其容量。
以下示范BitSet是如何工作的。
输出结果如下:
byte value: -107
bits: {0, 2, 4, 7}
bit pattern: 1010100100000000000000000000000000000000000000000000000000000000
short value: 1302
bits: {1, 2, 4, 8, 10}
bit pattern: 0110100010100000000000000000000000000000000000000000000000000000
int value: -2014573909
bits: {0, 1, 3, 5, 7, 9, 11, 18, 19, 21, 22, 23, 24, 25, 26, 31}
bit pattern: 1101010101010000001101111110000100000000000000000000000000000000
set bit 127: {127}
set bit 255: {255}
set bit 1023: {1023, 1024}
随机生成byte,short,int类型数值,每一个都被转换为BitSet中相应的位模式。因为BitSet初始为64位的,所以生成的随机数都不会导致其扩容。随后创建了一个更大的BitSet,可以看到Bit在必要时进行了扩。
如果你拥有一个可以命名的固定的标志集合,那么EnumSet与BitSet相比,更具有优势。因为EnumSet允许你按照名字而不是数字位置啦进行操作,可以减少错误。而且,EnumSet还可以防止你因不注意而添加新的位置标志。你应该使用BitSet的理由包括:只有在运行时才知道需要多少个标志位;对标志命名不合理;需要BitSet提供的特殊操作。
下面演示使用EnumSet替代传统的基于int的“位标志”。它是与枚举类型一起使用的专用 Set 实现。枚举 set 中所有键都必须来自单个枚举类型,该枚举类型在创建 set 时显式或隐式地指定。枚举 set 在内部表示为位向量。
输出结果:
[BATHROOM]
[STAIR1, STAIR2, BATHROOM, KITCHEN]
[LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, UTILITY]
[LOBBY, BATHROOM, UTILITY]
[STAIR1, STAIR2, OFFICE1, OFFICE2, OFFICE3, OFFICE4, KITCHEN]
如果要高效率的存贮大量开关信息,BitSet是很好的选择,不过它的效率是针对空间而言的;如果需要高效的访问时间,BitSet比本地数组稍慢一些。BitSet的最小容量是64位,如果存储的内容比较小,如8位。那么BitSet就浪费了一些空间。BitSet会随着元素的加入而扩充其容量。
以下示范BitSet是如何工作的。
package containers; //: containers/Bits.java // Demonstration of BitSet. import java.util.*; import static net.mindview.util.Print.*; public class Bits { public static void printBitSet(BitSet b) { print("bits: " + b); StringBuilder bbits = new StringBuilder(); for (int j = 0; j < b.size(); j++) bbits.append(b.get(j) ? "1" : "0"); print("bit pattern: " + bbits); } public static void main(String[] args) { Random rand = new Random(47); // Take the LSB of nextInt(): byte bt = (byte) rand.nextInt(); BitSet bb = new BitSet(); for (int i = 7; i >= 0; i--) if (((1 << i) & bt) != 0) bb.set(i); else bb.clear(i); print("byte value: " + bt); printBitSet(bb); short st = (short) rand.nextInt(); BitSet bs = new BitSet(); for (int i = 15; i >= 0; i--) if (((1 << i) & st) != 0) bs.set(i); else bs.clear(i); print("short value: " + st); printBitSet(bs); int it = rand.nextInt(); BitSet bi = new BitSet(); for (int i = 31; i >= 0; i--) if (((1 << i) & it) != 0) bi.set(i); else bi.clear(i); print("int value: " + it); printBitSet(bi); // Test bitsets >= 64 bits: BitSet b127 = new BitSet(); b127.set(127); print("set bit 127: " + b127); BitSet b255 = new BitSet(65); b255.set(255); print("set bit 255: " + b255); BitSet b1023 = new BitSet(512); b1023.set(1023); b1023.set(1024); print("set bit 1023: " + b1023); } }
输出结果如下:
byte value: -107
bits: {0, 2, 4, 7}
bit pattern: 1010100100000000000000000000000000000000000000000000000000000000
short value: 1302
bits: {1, 2, 4, 8, 10}
bit pattern: 0110100010100000000000000000000000000000000000000000000000000000
int value: -2014573909
bits: {0, 1, 3, 5, 7, 9, 11, 18, 19, 21, 22, 23, 24, 25, 26, 31}
bit pattern: 1101010101010000001101111110000100000000000000000000000000000000
set bit 127: {127}
set bit 255: {255}
set bit 1023: {1023, 1024}
随机生成byte,short,int类型数值,每一个都被转换为BitSet中相应的位模式。因为BitSet初始为64位的,所以生成的随机数都不会导致其扩容。随后创建了一个更大的BitSet,可以看到Bit在必要时进行了扩。
如果你拥有一个可以命名的固定的标志集合,那么EnumSet与BitSet相比,更具有优势。因为EnumSet允许你按照名字而不是数字位置啦进行操作,可以减少错误。而且,EnumSet还可以防止你因不注意而添加新的位置标志。你应该使用BitSet的理由包括:只有在运行时才知道需要多少个标志位;对标志命名不合理;需要BitSet提供的特殊操作。
下面演示使用EnumSet替代传统的基于int的“位标志”。它是与枚举类型一起使用的专用 Set 实现。枚举 set 中所有键都必须来自单个枚举类型,该枚举类型在创建 set 时显式或隐式地指定。枚举 set 在内部表示为位向量。
//: enumerated/AlarmPoints.java package enumerated; public enum AlarmPoints { STAIR1, STAIR2, LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, UTILITY, KITCHEN } // /:~
//: enumerated/EnumSets.java // Operations on EnumSets package enumerated; import java.util.*; import static enumerated.AlarmPoints.*; import static net.mindview.util.Print.*; public class EnumSets { public static void main(String[] args) { EnumSet<AlarmPoints> points = EnumSet.noneOf(AlarmPoints.class); // Empty // set points.add(BATHROOM); print(points); points.addAll(EnumSet.of(STAIR1, STAIR2, KITCHEN)); print(points); points = EnumSet.allOf(AlarmPoints.class); points.removeAll(EnumSet.of(STAIR1, STAIR2, KITCHEN)); print(points); points.removeAll(EnumSet.range(OFFICE1, OFFICE4)); print(points); points = EnumSet.complementOf(points); print(points); } }
输出结果:
[BATHROOM]
[STAIR1, STAIR2, BATHROOM, KITCHEN]
[LOBBY, OFFICE1, OFFICE2, OFFICE3, OFFICE4, BATHROOM, UTILITY]
[LOBBY, BATHROOM, UTILITY]
[STAIR1, STAIR2, OFFICE1, OFFICE2, OFFICE3, OFFICE4, KITCHEN]