在增长,缩小和克隆其价值后,Java BitSet的大小是多少?

时间:2015-12-08 17:07:06

标签: java memory-management clone bitset

bs1成为Java中的BitSet 第一位设置为bs1.set(0),其sizelength分别为64和1。 第65位设置为bs1.set(64),其sizelength分别为128和65.

现在,如果我清除它的第65位bs1.clear(64),它的length会回到1,但它的大小会发生什么变化? 如果我克隆bitset会发生什么?是新的尺寸默认值?

2 个答案:

答案 0 :(得分:0)

更少的单词和更多的代码,这里是我认为回答问题的实验:

    import java.util.BitSet;

public class BitSetExperiment {
    public static void main(String[] args) {
        BitSet bs0=new BitSet();
        BitSet bs1;
        System.out.println("created:\tLength,Size bs0: "+bs0.length()+" , "+bs0.size());
        bs0.set(15);
        System.out.println("set(15):\tLength,Size bs0: "+bs0.length()+" , "+bs0.size());
        bs0.set(63);
        System.out.println("set(63):\tLength,Size bs0: "+bs0.length()+" , "+bs0.size());
        bs0.set(86);
        System.out.println("set(86):\tLength,Size bs0: "+bs0.length()+" , "+bs0.size());
        bs0.clear(86);
        System.out.println("clear(86):\tLength,Size bs0: "+bs0.length()+" , "+bs0.size());
        bs0.clear(63);
        System.out.println("clear(63):\tLength,Size bs0: "+bs0.length()+" , "+bs0.size());

        System.out.println("Cloning to bs1...\n");
        bs1=(BitSet)bs0.clone();
        System.out.println("Length,Size bs0: "+bs0.length()+" , "+bs0.size());
        System.out.println("Length,Size bs1: "+bs1.length()+" , "+bs1.size());
    }
}

输出:

created:    Length,Size bs0: 0 , 64
set(15):    Length,Size bs0: 16 , 64
set(63):    Length,Size bs0: 64 , 64
set(86):    Length,Size bs0: 87 , 128
clear(86):  Length,Size bs0: 64 , 128
clear(63):  Length,Size bs0: 16 , 128
Cloning to bs1...

Length,Size bs0: 16 , 64
Length,Size bs1: 16 , 64

看看输出,我发现了两件事:

  1. 当你清除更重要的位时,BitSet不会修剪它的大小,但也许它是使用其他更复杂的机制完成的,如蜘蛛在他的评论中建议的@Boris。
  2. 克隆BitSet时,原始AND ALSO克隆以尽可能小的分配(64位因子)表示

答案 1 :(得分:0)

答案可能取决于实现方式。通过阅读Java 11源代码可以收集以下信息。

指定用于收缩BitSet的唯一API方法是trimToSize()

大多数(变异)API方法 可能会增加其大小,但永远不会减小它。

例外情况是clone()以及用于Java对象序列化的{private} readObjectwriteObject方法。这些方法的行为取决于一个称为sizeIsSticky的私有字段,而该私有字段又取决于该对象的先前历史记录。

如果创建的BitSet具有容量,则它的大小为粘性。除非BitSet超出其容量,否则大小将保持不变。

  • 克隆具有粘性大小的BitSet时,克隆对象具有相同的大小,并且大小也具有粘性。

  • 克隆具有非粘性大小的BitSet时,将首先修剪对象,然后创建克隆。克隆的大小不会发粘。

  • 序列化具有粘性大小的BitSet时,序列化的表格会保留大小。

  • 以非粘性大小序列化BitSet时,BitSet会在序列化之前被修剪。

  • 从序列号中反序列化BitSet时,其大小与序列号相同,并且粘滞性是通过启发式设置的。

当大小为非粘性时,在clone()writeObject中进行的修剪有点令人惊讶,但这就是(Java 11)代码所做的。通过sizeIsSticky字段上的注释来部分解释此行为。

/**
 * Whether the size of "words" is user-specified.  If so, we assume
 * the user knows what he's doing and try harder to preserve it.
 */
private transient boolean sizeIsSticky = false;