home *** CD-ROM | disk | FTP | other *** search
Java Source | 1997-05-20 | 9.1 KB | 343 lines |
- /*
- * @(#)BitSet.java 1.26 97/02/28
- *
- * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the confidential and proprietary information of Sun
- * Microsystems, Inc. ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
- * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- * CopyrightVersion 1.1_beta
- *
- */
-
- package java.util;
-
- /**
- * A set of bits. The set automatically grows as more bits are needed.
- *
- * @version 1.26, 02/28/97
- * @author Arthur van Hoff
- */
- public final class BitSet implements Cloneable, java.io.Serializable {
- private final static int BITS_PER_UNIT = 6;
- private final static int MASK = (1<<BITS_PER_UNIT)-1;
- private long bits[];
-
- /**
- * Convert bitIndex to a subscript into the bits[] array.
- */
- private static int subscript(int bitIndex) {
- return bitIndex >> BITS_PER_UNIT;
- }
- /**
- * Convert a subscript into the bits[] array to a (maximum) bitIndex.
- */
- private static int bitIndex(int subscript) {
- return (subscript << BITS_PER_UNIT) + MASK;
- }
-
- private static boolean debugging = (System.getProperty("debug") != null);
-
- /** use serialVersionUID from JDK 1.0.2 for interoperability */
- private static final long serialVersionUID = 7997698588986878753L;
-
- /**
- * Creates an empty set.
- */
- public BitSet() {
- this(1 << BITS_PER_UNIT);
- }
-
- /**
- * Creates an empty set with the specified size.
- * @param nbits the size of the set
- */
- public BitSet(int nbits) {
- /* nbits can't be negative; size 0 is OK */
- if (nbits < 0) {
- throw new NegativeArraySizeException(Integer.toString(nbits));
- }
- /* On wraparound, truncate size; almost certain to o-flo memory. */
- if (nbits + MASK < 0) {
- nbits = Integer.MAX_VALUE - MASK;
- }
- /* subscript(nbits + MASK) is the length of the array needed to hold nbits */
- bits = new long[subscript(nbits + MASK)];
- }
-
- /**
- * Ensures that the BitSet can hold at least an nth bit.
- * This cannot leave the bits array at length 0.
- * @param nth the 0-origin number of the bit to ensure is there.
- */
- private void ensureCapacity(int nth) {
- /* Doesn't need to be synchronized because it's an internal method. */
- int required = subscript(nth) + 1; /* +1 to get length, not index */
- if (required > bits.length) {
- /* Ask for larger of doubled size or required size */
- int request = Math.max(2 * bits.length, required);
- long newBits[] = new long[request];
- System.arraycopy(bits, 0, newBits, 0, bits.length);
- bits = newBits;
- }
- }
-
- /**
- * Sets a bit.
- * @param bit the bit to be set
- */
- public void set(int bit) {
- if (bit < 0) {
- throw new IndexOutOfBoundsException(Integer.toString(bit));
- }
- synchronized (this) {
- ensureCapacity(bit);
- bits[subscript(bit)] |= (1L << (bit & MASK));
- }
- }
-
- /**
- * Clears a bit.
- * @param bit the bit to be cleared
- */
- public void clear(int bit) {
- if (bit < 0) {
- throw new IndexOutOfBoundsException(Integer.toString(bit));
- }
- synchronized (this) {
- ensureCapacity(bit);
- bits[subscript(bit)] &= ~(1L << (bit & MASK));
- }
- }
-
- /**
- * Gets a bit.
- * @param bit the bit to be gotten
- */
- public boolean get(int bit) {
- if (bit < 0) {
- throw new IndexOutOfBoundsException(Integer.toString(bit));
- }
- boolean result = false;
- synchronized (this) {
- int n = subscript(bit); /* always positive */
- if (n < bits.length) {
- result = ((bits[n] & (1L << (bit & MASK))) != 0);
- }
- }
- return result;
- }
-
- /**
- * Logically ANDs this bit set with the specified set of bits.
- * @param set the bit set to be ANDed with
- */
- public void and(BitSet set) {
- /*
- * Need to synchronize both this and set.
- * This might lead to deadlock if one thread grabs them in one order
- * while another thread grabs them the other order.
- * Use a trick from Doug Lea's book on concurrency,
- * somewhat complicated because BitSet overrides hashCode().
- */
- if (this == set) {
- return;
- }
- BitSet first = this;
- BitSet second = set;
- if (System.identityHashCode(first) > System.identityHashCode(second)) {
- first = set;
- second = this;
- }
- synchronized (first) {
- synchronized (second) {
- int bitsLength = bits.length;
- int setLength = set.bits.length;
- int n = Math.min(bitsLength, setLength);
- for (int i = n ; i-- > 0 ; ) {
- bits[i] &= set.bits[i];
- }
- for (; n < bitsLength ; n++) {
- bits[n] = 0;
- }
- }
- }
- }
-
- /**
- * Logically ORs this bit set with the specified set of bits.
- * @param set the bit set to be ORed with
- */
- public void or(BitSet set) {
- if (this == set) {
- return;
- }
- /* See the note about synchronization in and(), above. */
- BitSet first = this;
- BitSet second = set;
- if (System.identityHashCode(first) > System.identityHashCode(second)) {
- first = set;
- second = this;
- }
- synchronized (first) {
- synchronized (second) {
- int setLength = set.bits.length;
- if (setLength > 0) {
- ensureCapacity(bitIndex(setLength-1));
- }
- for (int i = setLength; i-- > 0 ;) {
- bits[i] |= set.bits[i];
- }
- }
- }
- }
-
- /**
- * Logically XORs this bit set with the specified set of bits.
- * @param set the bit set to be XORed with
- */
- public void xor(BitSet set) {
- /* See the note about synchronization in and(), above. */
- BitSet first = this;
- BitSet second = set;
- if (System.identityHashCode(first) > System.identityHashCode(second)) {
- first = set;
- second = this;
- }
- synchronized (first) {
- synchronized (second) {
- int setLength = set.bits.length;
- if (setLength > 0) {
- ensureCapacity(bitIndex(setLength-1));
- }
- for (int i = setLength; i-- > 0 ;) {
- bits[i] ^= set.bits[i];
- }
- }
- }
- }
-
- /**
- * Gets the hashcode.
- */
- public int hashCode() {
- long h = 1234;
- synchronized (this) {
- for (int i = bits.length; --i >= 0; ) {
- h ^= bits[i] * (i + 1);
- }
- }
- return (int)((h >> 32) ^ h);
- }
-
- /**
- * Calculates and returns the set's size in bits.
- * The maximum element in the set is the size - 1st element.
- */
- public int size() {
- /* This doesn't need to be synchronized, since it just reads a field. */
- return bits.length << BITS_PER_UNIT;
- }
-
- /**
- * Compares this object against the specified object.
- * @param obj the object to compare with
- * @return true if the objects are the same; false otherwise.
- */
- public boolean equals(Object obj) {
- if ((obj != null) && (obj instanceof BitSet)) {
- if (this == obj) {
- return true;
- }
- BitSet set = (BitSet) obj;
- /* See the note about synchronization in and(), above. */
- BitSet first = this;
- BitSet second = set;
- if (System.identityHashCode(first) > System.identityHashCode(second)) {
- first = set;
- second = this;
- }
- synchronized (first) {
- synchronized (second) {
- int bitsLength = bits.length;
- int setLength = set.bits.length;
- int n = Math.min(bitsLength, setLength);
- for (int i = n ; i-- > 0 ;) {
- if (bits[i] != set.bits[i]) {
- return false;
- }
- }
- if (bitsLength > n) {
- for (int i = bitsLength ; i-- > n ;) {
- if (bits[i] != 0) {
- return false;
- }
- }
- } else if (setLength > n) {
- for (int i = setLength ; i-- > n ;) {
- if (set.bits[i] != 0) {
- return false;
- }
- }
- }
- }
- }
- return true;
- }
- return false;
- }
-
- /**
- * Clones the BitSet.
- */
- public Object clone() {
- BitSet result = null;
- synchronized (this) {
- try {
- result = (BitSet) super.clone();
- } catch (CloneNotSupportedException e) {
- // this shouldn't happen, since we are Cloneable
- throw new InternalError();
- }
- result.bits = new long[bits.length];
- System.arraycopy(bits, 0, result.bits, 0, result.bits.length);
- }
- return result;
- }
-
- /**
- * Converts the BitSet to a String.
- */
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- boolean needSeparator = false;
- buffer.append('{');
- synchronized (this) {
- int limit = size();
- for (int i = 0 ; i < limit ; i++) {
- if (get(i)) {
- if (needSeparator) {
- buffer.append(", ");
- } else {
- needSeparator = true;
- }
- buffer.append(i);
- }
- }
- }
- buffer.append('}');
- return buffer.toString();
- }
- }
-
-