有没有提供ImmutableBitSet
的Java库?我没有找到任何,也没有发现Guava也没有使用谷歌。
你可以使用BigInteger,因为它有setBit
,testBit
和clearBit
。
解决方法:
将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;
}
通过扩展它并使用抛出UnsupportedException或空块来淘汰修改器方法,很容易从java.util.BitSet中创建一个几乎不可变的BitSet。
但是,由于BitSet存储有效数据的字段不是最终的,因此您必须应用其中一个安全发布惯用语来实现线程安全(从here复制):
另一个解决方案可能是创建一个新的ImmutableBitSet类,将BitSet作为一个字段(带有final修饰符)嵌入其中,并将嵌入对象的reader方法委托给新类。
请注意,后一种解决方案不会破坏Liskow替换原则,而第一种解决方案不会。
我决定总结所有答案:
我认为没有办法让一切都变得完美,即获得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)
不是线程安全的,因为它们直接访问非final字段。所以这只是一次徒劳无功的运动。
如果想要实现所有方法以及转换到可变BitSet和从可变BitSet转换,那么使用BitInteger
是相当多的工作。因此,我建议使用委托或继承,具体取决于equals
的所需行为以及线程安全性的需要。
你可以使用BigInteger。它是不可变的,并且具有位操作方法。
就个人而言,我更喜欢EnumSet
而不是BitSet
。它被实现为一个位字段,但具有一个具有强命名的集合的API。真的,这是两全其美的。番石榴确实提供了ImmutableEnumSet
我已经在Apache Lucene项目中实现了基于org.apache.lucene.util.OpenBitSet的这类