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

问题描述 投票:0回答:3

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

现在,如果我清除它的第65位 bs1.clear(64),其 length 如果我克隆了比特集,新的比特集的大小是默认的吗?

java memory-management clone bitset
3个回答
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 the Spider在他的评论中所建议的那样。
  2. 当你克隆一个BitSet时,原来的AND和克隆的BitSet都用最小的分配来表示(64位的系数)。

0
投票

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

唯一指定的API方法是用来收缩一个 BitSettrimToSize().

大多数(突变的)API方法 增加它的大小,但绝不会减少它。

这方面的例外是 clone() 和(私人)的 readObjectwriteObject 方法,这些方法用于Java对象序列化。 这些方法的行为取决于一个叫做 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;
© www.soinside.com 2019 - 2024. All rights reserved.