package org.kefirsf.bb.util;
/**
* Best performance set of primitive type int
*
* @author Vitaliy Samolovskih aka Kefir
*/
public final class IntSet {
private static final int TABLE_SIZE = 256;
private static final int MASK = 255;
private static final int INITIAL_CAPACITY = 16;
private final int[][] table = new int[TABLE_SIZE][]; // Init null values by default
private final int[] lengths = new int[TABLE_SIZE]; // Init 0 values by default
public IntSet() {
}
public void add(int value) {
int rowIndex = rowIndex(value);
int[] row = table[rowIndex];
if (row == null) {
row = new int[INITIAL_CAPACITY];
table[rowIndex] = row;
row[0] = value;
lengths[rowIndex]++;
} else {
int length = lengths[rowIndex];
// Enlarge array if necessary
if (length >= row.length) {
int newLength = 2 * row.length;
int[] copyRow = new int[newLength];
System.arraycopy(row, 0, copyRow, 0, row.length);
row = copyRow;
table[rowIndex] = copyRow;
}
int index = binarySearch(row, length, value);
// If can't find value
if (index < 0) {
// Insert value
int temp = value;
for (int i = -index - 1; i < length; i++) {
int temp1 = row[i];
row[i] = temp;
temp = temp1;
}
row[length] = temp;
lengths[rowIndex]++;
}
}
}
/**
* Realisation of binary search algorithm. It is in JDK 1.6.0 but for
* JDK 1.5.0 compatibility I added it there.
*
* @param array array of integers values ordered by ascending
* @param toIndex top break of array
* @param key searched value
* @return value index or -(index of position)
*/
private static int binarySearch(int[] array, int toIndex, int key) {
int low = 0;
int high = toIndex - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
int midVal = array[mid];
if (midVal < key) {
low = mid + 1;
} else if (midVal > key) {
high = mid - 1;
} else {
return mid; // key found
}
}
return -(low + 1); // key not found.
}
public boolean contains(int value) {
int rowIndex = rowIndex(value);
int length = lengths[rowIndex];
return length > 0 && binarySearch(table[rowIndex], length, value) >= 0;
}
private static int rowIndex(int value) {
return value & MASK;
}
}