当需要用比较少的空间存储true和false时,不防考虑下通过bitmap实现。
bitmap用途还是非常广泛的,比如布隆过滤器等。
下面介绍如何用java实现一个bitmap用于存储状态数据(0/1、true/false)
public class BitMap {
/**
* 二进制数据存储,存储内容为[0,0,1,1]
*/
char[] binaryChars = null;
/**
* 扩张因子,当binaryChars小时,以该值扩张
*/
private static final double DILATATION_FACTOR = 1.3;
/**
* defaultChar 无状态时的值 因为存的为0,1所以无状态即为0
*/
private char defaultChar = '0';
/**
* valueChar 有状态时的值 因为存的为0,1所以无状态即为1
*/
private char valueChar = '1';
/**
* 将字符串转为BitMap
*
* @param data
*/
public BitMap(String data) {
// 转换为整数 Long大小有限制 使用bigInteger 无大小限制
BigInteger number = new BigInteger(data);
//转换为二进制
String binaryString = number.toString(2);
//转换为二进制字符数组
binaryChars = binaryString.toCharArray();
}
/**
* 创建大小为位数size的二进制
* 大小为size bitmap,使用set时index最大为size-1,否则会触发扩容
*
* @param size
*/
public BitMap(int size) {
binaryChars = new char[size];
for (int i = 0; i < binaryChars.length; i++) {
binaryChars[i] = defaultChar;
}
}
/**
* 默认10size
*/
public BitMap() {
this(10);
}
/**
* 返回当前数组长度
* 与 toString后生成的字符串的长度不同,toString会trim左边的0
* @return
*/
public int size() {
return binaryChars.length;
}
/**
* 对坐标赋值
*
* @param index 位置,从数组的右边开始向左递增,防止转为bigInteger时,省掉右边的0导致数据问题
* @param value true or false
*/
public void set(int index, boolean value) {
if (index >= binaryChars.length) {
//扩容
dilatation(index);
}
//从低位开始存,为了防止转数字时,丢掉高位
binaryChars[binaryChars.length - 1 - index] = value ? valueChar : defaultChar;
}
/**
* 扩容
*
* @param size 以size计算扩容后的数组大小
* 取+10 & *DILATATION_FACTOR 中的小值
*/
private void dilatation(int size) {
int max = Math.min(size + 10, (int) (size * DILATATION_FACTOR));
char[] temp = new char[max];
//从右边数据开始迁移到新的数组,如果不存在则置为defaultChar
for (int i = 0; i < temp.length; i++) {
if (i < binaryChars.length) {
temp[temp.length - 1 - i] = binaryChars[binaryChars.length - 1 - i];
} else {
temp[temp.length - 1 - i] = defaultChar;
}
}
binaryChars = temp;
}
/**
* 获取第index坐标上是否有值
*
* @param index
* @return
*/
public boolean get(int index) {
//如果该坐标大于了binaryChars.length则表示未存储,返回false
if (index >= binaryChars.length) {
return false;
}
//is equal valueChar
return binaryChars[binaryChars.length - 1 - index] == valueChar;
}
/**
* 转为string,通过BigInteger转时会丢掉左侧的0
*
* @return
*/
public String toString() {
BigInteger num = new BigInteger(new String(binaryChars), 2);
return String.valueOf(num);
}
/**
* toString
* @param radix 进制 如2
* @return
*/
public String toString(int radix){
BigInteger num = new BigInteger(new String(binaryChars), 2);
String binaryString = num.toString(radix);
return binaryString;
}
public static void main(String[] args) {
BitMap bitMapUtil = new BitMap(10);
bitMapUtil.set(0, true);
System.out.println(bitMapUtil);
bitMapUtil = new BitMap(bitMapUtil.toString());
bitMapUtil.set(11, true);
System.out.println(bitMapUtil);
System.out.println(bitMapUtil.get(11));
System.out.println(bitMapUtil.get(10));
System.out.println(bitMapUtil.get(100));
bitMapUtil.set(11, false);
System.out.println(bitMapUtil);
}
}