是否有任何Java库提供ImmutableBitSet
?我没有找到任何,也没有找到Guava,也没有使用谷歌。
答案 0 :(得分:6)
您可以使用BigInteger,因为它有setBit
,testBit
和clearBit
。
答案 1 :(得分:3)
通过扩展它并使用抛出UnsupportedException 或空块来删除修饰符方法,很容易从 java.util.BitSet 创建一个几乎不可变的BitSet。
但是,由于存储有效数据的BitSet字段不是 final ,因此您必须应用其中一个安全发布惯用语来实现线程安全性(从here复制):< / p>
另一个解决方案是创建一个新的ImmutableBitSet类,将BitSet作为一个字段嵌入到它中(带有final修饰符),并将嵌入对象的reader方法委托给新类。
请注意,后一种解决方案不会破坏Liskow替换原则,而第一种解决方案不会。
答案 2 :(得分:3)
解决方法:
将BitSet存储在私有字段中,并使用克隆公共方法公开它:
private final BitSet bits;
public BitSet bits(){
return (BitSet) bits.clone();
}
或:
private final BitSet bits;
public BitSet bits(){
BitSet clone = new BitSet();
clone.or(bits);
return clone;
}
答案 3 :(得分:3)
我决定总结所有答案:
我认为没有办法让一切都变得完美,即获得BitSet
的不可变子类,以便equals
以线程安全的方式工作。我承认我没有在问题中陈述我的所有要求。
继承BitSet
并让所有mutator方法抛出异常很容易并且有效。唯一的问题是从equals
调用的BitSet
本身不是线程安全的,因为它直接访问非最终的继承字段。通过下面描述的技巧可以使所有其他方法成为线程安全的。
委派给BitSet
也很容易且有效,唯一的问题是BitSet
不能等于ImmutableBitSet
。请注意,为了线程安全,委托必须存储在最终字段中。
结合继承和委派看起来很有希望:
public class ImmutableBitSet extends BitSet {
private final ImmutableBitSet delegate;
public ImmutableBitSet(BitSet original) {
or(original); // copy original to this
delegate = this; // initialize a final reference for thread safety
}
@Override // example mutator method
public void and(BitSet set) {
throw new UnsupportedOperationException();
}
@Override // example non-mutator method
public boolean get(int bitIndex) {
return delegate.getPrivate(bitIndex);
}
// needed in order to avoid endless recursion
private boolean getPrivate(int bitIndex) {
super.get(bitIndex);
}
...
}
看起来很奇怪,但效果近乎完美。对bitSet.equals(immutableBitSet)
的调用不是线程安全的,因为它们直接访问非最终字段。所以这只是一次徒劳无功的运动。
如果想要实现所有方法并在可变BitSet中进行转换,那么使用BitInteger
是相当多的工作。所以我建议使用委托或继承,具体取决于equals
的所需行为以及线程安全的需要。
答案 4 :(得分:2)
您可以使用BigInteger。它是不可变的,并且有位操作方法。
答案 5 :(得分:2)
就我个人而言,我更喜欢EnumSet
而不是BitSet
。它被实现为一个位字段,但具有一个具有强命名的集合的API。真的,这是两全其美的。番石榴确实提供ImmutableEnumSet
答案 6 :(得分:1)
我已经在Apache Lucene项目中实现了基于org.apache.lucene.util.OpenBitSet的这样的