Java中有ImmutableBitSet吗?

问题描述 投票:11回答:7

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

java collections guava
7个回答
6
投票

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


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
投票

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

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

  • 从静态初始化程序初始化对象引用;
  • 将对它的引用存储到volatile字段或AtomicReference中;
  • 将对它的引用存储到正确构造的对象的最终字段中
  • 将对它的引用存储到由锁正确保护的字段中。

另一个解决方案可能是创建一个新的ImmutableBitSet类,将BitSet作为一个字段(带有final修饰符)嵌入其中,并将嵌入对象的reader方法委托给新类。

请注意,后一种解决方案不会破坏Liskow替换原则,而第一种解决方案不会。


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)不是线程安全的,因为它们直接访问非final字段。所以这只是一次徒劳无功的运动。

如果想要实现所有方法以及转换到可变BitSet和从可变BitSet转换,那么使用BitInteger是相当多的工作。因此,我建议使用委托或继承,具体取决于equals的所需行为以及线程安全性的需要。


2
投票

你可以使用BigInteger。它是不可变的,并且具有位操作方法。


2
投票

就个人而言,我更喜欢EnumSet而不是BitSet。它被实现为一个位字段,但具有一个具有强命名的集合的API。真的,这是两全其美的。番石榴确实提供了ImmutableEnumSet


1
投票

我已经在Apache Lucene项目中实现了基于org.apache.lucene.util.OpenBitSet的这类

http://www.dishevelled.org/bitset

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

© www.soinside.com 2019 - 2024. All rights reserved.