设为 bs1
Java中的一个BitSet。第一个位被设置为 bs1.set(0)
那么,其 size
和 length
分别为64和1。第65位设置为 bs1.set(64)
那么,其 size
和 length
分别为128和65。
现在,如果我清除它的第65位 bs1.clear(64)
,其 length
如果我克隆了比特集,新的比特集的大小是默认的吗?
字数少了,代码多了,这里的实验,在我看来是回答了这个问题。
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
从输出结果来看,我发现了两件事:
答案可能取决于实现。 以下信息是通过阅读Java 11源代码收集到的。
唯一指定的API方法是用来收缩一个 BitSet
是 trimToSize()
.
大多数(突变的)API方法 可 增加它的大小,但绝不会减少它。
这方面的例外是 clone()
和(私人)的 readObject
和 writeObject
方法,这些方法用于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;