Java中有ImmutableBitSet吗?

时间:2011-08-11 09:56:10

标签: java collections guava

是否有任何Java库提供ImmutableBitSet?我没有找到任何,也没有找到Guava,也没有使用谷歌。

7 个答案:

答案 0 :(得分:6)

您可以使用BigInteger,因为它有setBittestBitclearBit

答案 1 :(得分:3)

通过扩展它并使用抛出UnsupportedException 或空块来删除修饰符方法,很容易从 java.util.BitSet 创建一个几乎不可变的BitSet。

但是,由于存储有效数据的BitSet字段不是 final ,因此您必须应用其中一个安全发布惯用语来实现线程安全性(从here复制):< / p>

  • 从静态初始化程序初始化对象引用;
  • 将对它的引用存储到易失性字段或AtomicReference中;
  • 将对它的引用存储到正确构造的对象的最终字段中
  • 将对它的引用存储到受到适当保护的字段中 一把锁。

另一个解决方案是创建一个新的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的这样的

http://www.dishevelled.org/bitset

http://www.dishevelled.org/bitset/apidocs/index.html