在Java中,我想要存储(>10'000)个长度为32的布尔数组(boolean[])到磁盘,并且以后可以再次读取它们进行进一步的计算和比较。
由于单个数组的长度为32,我想知道是否将其存储为整数值以加快读写速度(在32位机器上)是有意义的。您是否建议使用BitSet,然后转换为int?或者完全不考虑int并使用字节?
在Java中,我想要存储(>10'000)个长度为32的布尔数组(boolean[])到磁盘,并且以后可以再次读取它们进行进一步的计算和比较。
由于单个数组的长度为32,我想知道是否将其存储为整数值以加快读写速度(在32位机器上)是有意义的。您是否建议使用BitSet,然后转换为int?或者完全不考虑int并使用字节?
对于二进制存储,使用int
和DataOutputStream
(读取时使用DataInputStream
)。
我认为在Java中,布尔数组在内部被存储为字节数组或整数数组,因此您可能希望考虑避免开销并始终保持整数编码,即根本不使用boolean[]
。
相反,可以这样做:
public class BooleanArray32 {
private int values;
public boolean get(int pos) {
return (values & (1 << pos)) != 0;
}
public void set(int pos, boolean value) {
int mask = 1 << pos;
values = (values & ~mask) | (value ? mask : 0);
}
public void write(DataOutputStream dos) throws IOException {
dos.writeInt(values);
}
public void read(DataInputStream dis) throws IOException {
values = dis.readInt();
}
public int compare(BooleanArray32 b2) {
return countBits(b2.values & values);
}
// From http://graphics.stanford.edu/~seander/bithacks.html
// Disclaimer: I did not fully double check whether this works for Java's signed ints
public static int countBits(int v) {
v = v - ((v >>> 1) & 0x55555555); // reuse input as temporary
v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); // temp
return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
}
}
我强烈印象,任何压缩布尔值的尝试都会增加读写时间(我的错误,显然是因为我忘记吃药了)。相反,您将在所涉及的存储方面获得收益。
BitSet是您业务逻辑方面明智的选择。它在内部存储一个long,您可以将其转换为int。但是,由于BitSet足够谨慎,不会向您显示其私有内容,因此您需要按顺序获取每个位索引。这意味着我猜想与其转换为int,直接使用字节可能没有真正的优势。
因此,Stefan Haustein的自制解决方案(必要时扩展以模仿BitSet)对于您的存储需求更可取,因为您不会产生任何不必要的开销。