Java中是否存在用于稀疏位向量的任何着名库?
(是否有关于稀疏对于java.util.BitSet使用它们有用的指导原则?)
答案 0 :(得分:8)
TL; DR到这里Efficient Sparse BitSet implementation in Java
我知道这是一个“老”的问题,但我遇到了同样的问题,我偶然发现了这篇文章。虽然答案很好,但我最终并不满意。在进一步挖掘之后,我想我已经遇到了Java中稀疏BitSet问题的“权威”答案。
在this presentation作者Bruce Haddon博士讨论了他的研究人员为标准Java BitSet创建高内存效率和高性能替代品的努力。
他演示文稿的原始链接已经死了,但我联系了Haddon博士,并保留了代码和演示文稿:
https://github.com/brettwooldridge/SparseBitSet
我不建议更高度阅读此演示文稿。即使您对稀疏位集没有兴趣,它也是一个引人入胜的读物,更多的是关于解决问题的本质......
Slides: Is it Computer Science, Software Engineering, or Hacking?
答案 1 :(得分:4)
如果它真的稀疏(例如,加载小于1%),那么使用由位索引索引的哈希表可能相当不错;如果该位分别为1或0,则只需要知道表中是否存在索引。
如果密度高达百分之几,则可以使用由位索引除以64的哈希表,并在包含实际位的哈希表中存储长字。如果哈希表包含 int(N / 64)和(V>>(N)的值 V ,则设置位 N mod 64))& 1 是真的。
这两个答案都假设您希望优化对位的随机访问。如果要按索引优化对位的顺序(或其他访问),则可能需要稀疏矩阵结构,使用相同类型的低级位向量表示,具体取决于预期的密度。见Sparse Matrices
答案 2 :(得分:3)
colt library具有稀疏矩阵(1D,2D和3D)。它还有一个高效的BitVector,每个值1位,而不是boolean[]
的8位。
然而,稀疏矩阵不直接支持位 - 只有双精度和对象。您可以通过将位索引maping到长索引(bitIndex>>6)
来包装1D稀疏双矩阵,因为每个long保持64位,convert将检索到的double加到原始long值,并使用位操作来访问检索到的长。一点点工作,但远不及自己实现稀疏矢量那么多。一旦你的包装器工作,你可能会避免将双精度转换为long,并使用双重1D稀疏矩阵的可用Colt源代码作为起点来实现一个真正的稀疏长1d矩阵。
编辑:更多信息。假设所有位(长)最初为0,Colt向量/矩阵最初不需要存储器用于存储。将值设置为非零会占用内存。将值设置回0会继续消耗内存,但会定期回收零值的内存。
如果这些位真的是稀疏的,这样每个后备long值只有一个位设置,那么存储开销将非常差,每个实际位需要存储64位。但是当你提到典型的情况是20-40%稀疏时,那么开销会低很多,如果比特在范围内聚集,可能没有浪费的存储,例如, 0-100,然后1000-1100和2000-2200(十六进制值)的位。总的来说,只有1/16的区域被分配给位,但是聚类意味着存储的位没有浪费的空间。
答案 3 :(得分:1)
您可以尝试FastUtil's AVL Tree Map。
答案 4 :(得分:0)
CERN COLT广泛用于向量和矩阵计算,并且具有稀疏矩阵,但并未专门用于位向量。
http://acs.lbl.gov/software/colt/api/cern/colt/matrix/impl/SparseObjectMatrix1D.html
答案 5 :(得分:0)
仅仅存在或不存在密钥的哈希表会告诉您什么?那将是一个哈希集!我对BitSet上的一个集合(甚至是一个哈希值)的性能持怀疑态度。这实际上取决于速度或内存是否是主要驱动因素。
答案 6 :(得分:0)