简体   繁体   中英

What is the Java BitSet size after growing, shrinking and cloning its value?

Let be bs1 a BitSet in Java.
The first bit is set bs1.set(0) , then its size and length are 64 and 1 respectively.
The 65th bit is set bs1.set(64) , then its size and length are 128 and 65 respectively.

Now, if I clear its 65th bit bs1.clear(64) , its length go back to 1, but what happen with its size? What happen if I clone the bitset? is the new one's size default?

Less words and more code, here the experiment that in my opinion answers the question:

    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());
    }
}

The output:

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

Looking at the output, I found two things:

  1. When you clear the more significant bits the BitSet DOES NOT trim its size, but maybe it is done using another mechanisms more sophisticated as @Boris the Spider suggest in his comment.
  2. When you clone a BitSet, the original AND ALSO the clone are represented in the smallest possible allocation (in factors of 64 bits)

The answer could depend on the implementation. The following information was gleaned by reading the Java 11 source code.

The only API method that is specified to shrink a BitSet is trimToSize() .

Most (mutating) API methods may increase its size, but won't ever reduce it.

The exception to this are clone() and the (private) readObject and writeObject methods that are used for Java object serialization. The behavior of these methods depend on a private field called sizeIsSticky which in turn depends on the previous history of the object.

If the BitSet is created with a capacity, it has a sticky size. The size will stay stick unless the BitSet grows beyond its capacity.

  • When you clone a BitSet with a sticky size, the clone object has the same size and the size is also sticky.

  • When you clone a BitSet with a non-sticky size, the object is ffirst trimmed and then the clone is creates. The clone's size will be non-sticky.

  • When you serialize a BitSet with a sticky size, the serialized form preserves the size.

  • When you serialize BitSet with a non-sticky size, the BitSet is trimmed before serializing.

  • When you deserialize a BitSet from its serial form, the size is the same as for the serial form, and the stickyness is set heuristically.

The trimming that happens in clone() and writeObject when the size is non-sticky is a bit surprising, but that is what the (Java 11) code does. The behavior is partly explained by the comment on the sizeIsSticky field.

/**
 * 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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM