BitSet Basics The BitSet class represents a set of bits where the set grows in size as needed.. Printing Bit Sets The BitSet class overrides the toString method inherited from Object: pu
Trang 1Chapter 6: The BitSet Class
Overview
The BitSet class is the least used of the historical collection classes In this chapter, you'll learn where the class fits in with the remaining collections, as well as how to effectively use the class within your Java
programs
The BitSet class provides a memory−efficient abstraction for a collection of bits In other words, the class represents a growable, array−like structure of boolean values In fact, a BitSet can grow without bounds to provide an infinitely large set of indexed boolean values As shown in Figure 6−1, there isn't anything special about the BitSet class It is your basic Object subclass, which implements the Cloneable and Serializable interfaces
Figure 6−1: The BitSet class hierarchy
Note In Chapter 8 of this book, you'll learn about the Set interface with its HashSet and TreeSet
implementations As Figure 6−1 shows, the BitSet class is not another implementation of the Set
interface
BitSet Basics
The BitSet class represents a set of bits where the set grows in size as needed Each indexed element of the set
is a bit with a value of zero or one A zero setting means the bit is clear (or false if you want to think in terms
of boolean values), while a one represents the bit as set Table 6−1 shows the set of methods provided with the BitSet class
Table 6−1: Summary of BitSet Class
VARIABLE/METHOD NAME VERSION DESCRIPTION
BitSet() 1.0 Creates a bit set with all bits clear
and() 1.0 Performs a logical AND operation with another bit set andNot() 1.2 Performs a logical NOT operation of another bit set,
then performs a logical AND operation with this bit set
clear() 1.0 Clears a specific bit of the set
equals() 1.0 Checks for equality with another object
get() 1.0 Gets the setting of a specific bit from the set
hashCode() 1.0 Returns computed hashcode for the bit set
length() 1.2 Returns the logical size of the set
or() 1.0 Performs a logical OR operation with another bit set
Trang 2set() 1.0 Sets a specific bit of the set.
size() 1.0 Returns the internal space used to represent the bit set toString() 1.0 Converts the bit set contents into a string
xor() 1.0 Performs a logical XOR operation with another bit set
Creating Bit Sets
There are two ways to create a BitSet You can either specify an initial bit set size, or not:
public BitSet()
public BitSet(int nbits)
If you don't specify a size, an internal structure will be created to store sixty−four different bit settings If you
do specify a size, the structure size will be rounded up to the nearest multiple of sixty−four
Note A NegativeArraySizeException will be thrown if the initial size is negative.
When a bit set is created, all bits in the set are clear, or set to zero After creating the set, if setting or clearing bits happens at a higher position than the current set size, the set size will grow
Printing Bit Sets
The BitSet class overrides the toString() method inherited from Object:
public String toString()
The string generated by calling the toString() method is a comma−delimited list of set bit positions, which is set and is surrounded by curly braces ({ }) For example, if the bits at position 0, 36, and 42 were set, calling toString() would generate the following string:
{0, 36, 42}
When a BitSet is first created, the returned string is the empty set:
{}
Bit Set Operations
Once you've created the bit set, you can work with either individual bits or the set as a whole
Manipulating Individual Bits
When working with individual bits, you usually need to change or get their setting There are two methods for changing the setting: set() and clear() There is one for getting: get() Each of the methods accepts a position argument to specify the zero−based index of the bit to change
public void set(int position)
public void clear(int position)
Creating Bit Sets
Trang 3public boolean get(int position)
If the position specified in the set() method is beyond the size of the bit set, the set grows in increments of sixty−four Calling clear() with a position beyond the set size does nothing If the position specified in a call
to get() is beyond the set size, false is returned without growing the set For valid position sizes, true is
returned if the position is set (1), or false if clear (0) For all three methods, if the position is negative, an IndexOutOfBoundsException will be thrown
Manipulating Sets of Bits
There are four methods for performing set−wide operations on the bit set Each performs a logical operation
of the corresponding bits of the two sets:
public void and(BitSet set)
public void or(BitSet set)
public void xor(BitSet set)
public void andNot(BitSet set)
For the AND operation, each bit in the current bit set will be set (1) if it is already set and if the corresponding bit in the passed−in set is also set This roughly equates to the following:
this[index] &= set[index]
For the OR operation, the bit in the current bit set will be set (1) if it is already set or if the corresponding bit
in the passed in set is set This can be expressed as:
this[index] |= set[index]
For the XOR operation, the bit in the current bit set will be set (1) if it is already set or if the corresponding bit
in the passed−in set is set, but not if both bits are set Or, looked at in another way, the bit is set if it differs from the corresponding bit in the passed−in set and is cleared if it is the same This can be expressed as:
this[index] ^= set[index]
For the NAND (not add) operation, the bit in the current bit set will be cleared (0) if the corresponding bit is already set in the passed in set This roughly equates to the following:
this[index] &= ~set[index]
To demonstrate these four operations, Table 6−2 shows what happens when you perform the different
operations with an original bit set of {1, 2, 3, 4, 5} and a passed in set of {1, 3, 5, 7}
Table 6−2: Set Manipulation
OPERATION RESULTS
and() {1, 3, 5}
or() {1, 2, 3, 4, 5, 7}
xor() {2, 4, 7}
andNot() {2, 4}
Manipulating Sets of Bits
Trang 4If there is a size difference between the two sets, the size of the resulting set depends on the method called Under no condition will the contents of the passed−in set change in size or content as a result of the method call
and(): If the size of the current set is smaller than the passed−in set, the extra bits are ignored If the size of the current set is larger than the passed−in set, the extra bits are cleared/set to zero
•
or() / xor(): If the size of the current set is smaller than the passed−in set, the size of the current set is increased to match the size of the passed−in set All new bits are cleared/set to zero before performing the operation
•
andNot(): If the sizes are different in either direction, the extra bits are ignored/unchanged
•
Note A NullPointerException will be thrown if you pass in a null set to any of these methods.
Determining Set Size
Think of a BitSet as a dynamically growing array composed of bits, similar to a vector This dynamically growing structure has two values describing its internal dimensions: a size and a length
public int size()
public int length()
The size() method will return the number of bits reserved in the set and grows in increments of sixty−four Think of this value like the capacity when working with a vector On the other hand, the length() of a bit set is the last position that is set Since positions are indexed starting from zero, this equates to the index of the highest set bit plus one
Note One odd behavior of a bit set's length is that if you clear the highest set bit, the set's length can drop more than one depending upon where the next highest set bit is located
Cloning Bit Sets
The BitSet class implements the Cloneable interface, providing you with a clone() method
public Object clone()
When you clone() a BitSet, you create another set with the same size and the same bit positions set
Checking Bit Sets for Equality
The BitSet class overrides the equals() method from Object to define the equality of bit sets
public boolean equals(Object object)
Two bit sets are defined as equal if both bit sets have the same set or clear state at every position In other words, this[index]=object[index] must be true for each index in both sets When one set is shorter than the other, the remaining elements would need to be clear in the longer set for both sets to be equal
Hashing Bit Sets
Besides overriding the equals() method of Object, the BitSet class also overrides the hashCode() method The generated hash code is only based on the position of the set bits:
Determining Set Size
Trang 5public int hashCode()
Using BitSet: an Example
To demonstrate the usage of the BitSet class, Listing 6−1 creates a set of candy where the bit is set if the name has an even number of characters It then prints out all the odd types of candy and shows the set size and length Finally, it demonstrates the andNot() method by combining the first set with a second set where the first four elements are all set
Listing 6−1: Demonstrating the use of BitSet
import java.util.BitSet;
public class BitOHoney {
public static void main (String args[]) {
String names[] = {
"Hershey's Kisses", "Nestle's Crunch",
"Snickers", "3 Musketeers",
"Milky Way", "Twix", "Mr Goodbar",
"Crunchie", "Godiva", "Charleston Chew",
"Cadbury's", "Lindt", "Aero", "Hebert",
"Toblerone", "Smarties", "LifeSavers",
"Riesen", "Goobers", "Raisinettes", "Nerds",
"Tootsie Roll", "Sweet Tarts", "Cotton Candy"};
BitSet bits = new BitSet();
for (int i=0, n=names.length; i<n; i++) {
if ((names[i].length() % 2) == 0) {
bits.set(i);
}
}
System.out.println(bits);
System.out.println("Size : " + bits.size());
System.out.println("Length: " + bits.length());
for (int i=0, n=names.length; i<n; i++) {
if (!bits.get(i)) {
System.out.println(names[i] + " is odd");
}
}
BitSet bites = new BitSet();
bites.set(0);
bites.set(1);
bites.set(2);
bites.set(3);
bites.andNot(bits);
System.out.println(bites);
}
}
When run, this program produces this output:
{0, 2, 3, 5, 7, 8, 12, 13, 15, 16, 17, 21, 23}
Size : 64
Length: 24
Nestle's Crunch is odd
Using BitSet: an Example
Trang 6Milky Way is odd
Mr Goodbar is odd
Charleston Chew is odd
Cadbury's is odd
Lindt is odd
Toblerone is odd
Goobers is odd
Raisinettes is odd
Nerds is odd
Sweet Tarts is odd
{1}
Tip The 1.1 version of this class was final with many of the operations of the class synchronized
(internally) That is no longer the case.You can now subclass BitSet If thread safety is an issue,
you'll need to call the necessary methods within a synchronized block The 1.0 version of the class didn't grow properly under certain conditions
Summary
In this chapter, we concluded our look at the historical collection classes by examining the BitSet class You saw how to perform many operations with the bit set, from working with single bits to combining and
comparing multiple bit sets It is important to remember when working with BitSet that it is only beneficial for large sets of bits Otherwise, it's just as easy to use a Vector of Boolean objects
The next chapter begins Part Two in which we'll examine the Collections Framework introduced with the Java
2 release We'll start by looking at the base Collection and Iterator interfaces of the framework
Summary