BitSet与EnumSet的根本使用

BitSet与EnumSet的基本使用
   如果要高效率的存贮大量开关信息,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]