bitkey.java
来自「数据仓库展示程序」· Java 代码 · 共 455 行 · 第 1/2 页
JAVA
455 行
/*
// $Id: //open/mondrian/src/main/mondrian/rolap/BitKey.java#2 $
// This software is subject to the terms of the Common Public License
// Agreement, available at the following URL:
// http://www.opensource.org/licenses/cpl.html.
// (C) Copyright 2001-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, 30 August, 2001
*/
package mondrian.rolap;
/**
* Represents a set of bits.
*
* <p>Unlike {@link java.util.BitSet}, the number of bits cannot be changed
* after the BitKey is created. This allows us to optimize.
*
* <p>If you have a collection of immutable objects, each of which has a unique
* positive number and you wish to do comparisons between subsets of those
* objects testing for equality, then encoding the subsets as BitKeys is very
* efficient.
*
* <p>There are two implementations that target groups of objects with maximum
* number less than 64 and less than 128; and there is one implements that is
* general for any positive number.
*
* <p>One caution: if the maximum number assigned to one of the
* objects is large, then this representation might be sparse and therefore
* not efficient.
*
* @author <a>Richard M. Emberson</a>
* @version
*/
public interface BitKey {
void setByPos(int pos, boolean value);
void setByPos(int pos);
boolean isSetByPos(int pos);
void clearByPos(int pos);
void clear();
/**
* Is every bit set in the parameter <code>bitKey</code> also set in
* <code>this</code>.
* If one switches <code>this</code> with the parameter <code>bitKey</code>
* one gets the equivalent of isSubSetOf.
*
* @param bitKey
*/
boolean isSuperSetOf(BitKey bitKey);
public BitKey copy();
public abstract class Factory {
/**
* Creates a {@link BitKey} with a capacity for a given number of bits.
* @param size Number of bits in key
*/
public static BitKey makeBitKey(int size) {
if (size < 0) {
String msg = "Negative size \"" + size + "\" not allowed";
throw new IllegalArgumentException(msg);
}
switch (AbstractBitKey.chunkCount(size)) {
case 0:
case 1:
return new BitKey.Small();
case 2:
return new BitKey.Mid128();
default:
return new BitKey.Big(size);
}
}
}
/**
* Abstract implementation of {@link BitKey}.
*/
abstract class AbstractBitKey implements BitKey {
protected AbstractBitKey() {
}
// chunk is a long, which has 64 bits
protected static final int ChunkBitCount = 6;
protected static final int Mask = 63;
/**
* Creates a chunk containing a single bit.
*/
protected static long bit(int pos) {
return (1L << (pos & Mask));
}
/**
* Returns which chunk a given bit falls into.
* Bits 0 to 63 fall in chunk 0, bits 64 to 127 fall into chunk 1.
*/
protected static int chunkPos(int size) {
return (size >> ChunkBitCount);
}
/**
* Returns the number of chunks required for a given number of bits.
* 0 bits requires 0 chunks; 1 - 64 bits requires 1 chunk; etc.
*/
protected static int chunkCount(int size) {
return (size + 63) >> ChunkBitCount;
}
public final void setByPos(int pos, boolean value) {
if (value) {
setByPos(pos);
} else {
clearByPos(pos);
}
}
}
/**
* Implementation of {@link BitKey} for bit counts less than 64.
*/
public class Small extends AbstractBitKey {
private long bits;
private Small() {
}
private Small(Small small) {
this.bits = small.bits;
}
public void setByPos(int pos) {
bits |= bit(pos);
}
public boolean isSetByPos(int pos) {
return ((bits & bit(pos)) != 0);
}
public void clearByPos(int pos) {
bits &= ~bit(pos);
}
public void clear() {
bits = 0;
}
public boolean isSuperSetOf(BitKey bitKey) {
if (bitKey instanceof BitKey.Small) {
BitKey.Small other = (BitKey.Small) bitKey;
return ((this.bits | other.bits) == this.bits);
} else if (bitKey instanceof BitKey.Mid128) {
BitKey.Mid128 other = (BitKey.Mid128) bitKey;
return ((this.bits | other.bits0) == this.bits) &&
(other.bits1 == 0);
} else if (bitKey instanceof BitKey.Big) {
BitKey.Big other = (BitKey.Big) bitKey;
if ((this.bits | other.bits[0]) != this.bits) {
return false;
} else {
for (int i = 1; i < other.bits.length; i++) {
if (other.bits[i] != 0) {
return false;
}
}
return true;
}
}
return false;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof BitKey.Small) {
BitKey.Small other = (BitKey.Small) o;
return (this.bits == other.bits);
} else if (o instanceof BitKey.Mid128) {
BitKey.Mid128 other = (BitKey.Mid128) o;
return (this.bits == other.bits0) && (other.bits1 == 0);
} else if (o instanceof BitKey.Big) {
BitKey.Big other = (BitKey.Big) o;
if (this.bits != other.bits[0]) {
return false;
} else {
for (int i = 1; i < other.bits.length; i++) {
if (other.bits[i] != 0) {
return false;
}
}
return true;
}
}
return false;
}
public int hashCode() {
return (int)(bits ^ (bits >>> 32));
}
public String toString() {
StringBuffer buf = new StringBuffer(64);
buf.append("0x");
for (int i = 63; i >= 0; i--) {
buf.append((isSetByPos(i)) ? '1' : '0');
}
return buf.toString();
}
public BitKey copy() {
return new Small(this);
}
}
/**
* Implementation of {@link BitKey} good for sizes less than 128.
*/
public class Mid128 extends AbstractBitKey {
private long bits0;
private long bits1;
private Mid128() {
}
private Mid128(Mid128 mid) {
this.bits0 = mid.bits0;
this.bits1 = mid.bits1;
}
public void setByPos(int pos) {
if (pos < 64) {
bits0 |= bit(pos);
} else {
bits1 |= bit(pos);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?