org.eclipse.mat.collect.HashMapIntLong Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of haha Show documentation
Show all versions of haha Show documentation
Java library to automate the analysis of Android heap dumps.
/**
* ****************************************************************************
* Copyright (c) 2008 SAP AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP AG - initial API and implementation
* *****************************************************************************
*/
package org.eclipse.mat.collect;
import java.io.Serializable;
import java.util.Iterator;
import java.util.NoSuchElementException;
public final class HashMapIntLong implements Serializable {
public interface Entry {
int getKey();
long getValue();
}
private static NoSuchElementException noSuchElementException = new NoSuchElementException(
"This is static exception, there is no stack trace available. It is thrown by get() method.");
//$NON-NLS-1$
private static final long serialVersionUID = 1L;
private int capacity;
private int step;
private int limit;
private int size;
private boolean[] used;
private int[] keys;
private long[] values;
public HashMapIntLong() {
this(10);
}
public HashMapIntLong(int initialCapacity) {
init(initialCapacity);
}
public boolean put(int key, long value) {
if (size == limit) resize(capacity << 1);
int hash = (key & Integer.MAX_VALUE) % capacity;
while (used[hash]) {
if (keys[hash] == key) {
values[hash] = value;
return true;
}
hash = (hash + step) % capacity;
}
used[hash] = true;
keys[hash] = key;
values[hash] = value;
size++;
return false;
}
public boolean remove(int key) {
int hash = (key & Integer.MAX_VALUE) % capacity;
while (used[hash]) {
if (keys[hash] == key) {
used[hash] = false;
size--;
// Re-hash all follow-up entries anew; Do not fiddle with the
// capacity limit (75 %) otherwise this code may loop forever
hash = (hash + step) % capacity;
while (used[hash]) {
key = keys[hash];
used[hash] = false;
int newHash = (key & Integer.MAX_VALUE) % capacity;
while (used[newHash]) {
newHash = (newHash + step) % capacity;
}
used[newHash] = true;
keys[newHash] = key;
values[newHash] = values[hash];
hash = (hash + step) % capacity;
}
return true;
}
hash = (hash + step) % capacity;
}
return false;
}
public boolean containsKey(int key) {
int hash = (key & Integer.MAX_VALUE) % capacity;
while (used[hash]) {
if (keys[hash] == key) {
return true;
}
hash = (hash + step) % capacity;
}
return false;
}
public long get(int key) {
int hash = (key & Integer.MAX_VALUE) % capacity;
while (used[hash]) {
if (keys[hash] == key) {
return values[hash];
}
hash = (hash + step) % capacity;
}
throw noSuchElementException;
}
public int[] getAllKeys() {
int[] array = new int[size];
int j = 0;
for (int i = 0; i < used.length; i++) {
if (used[i]) {
array[j++] = keys[i];
}
}
return array;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size() == 0;
}
public void clear() {
size = 0;
used = new boolean[capacity];
}
public IteratorInt keys() {
return new IteratorInt() {
int n = 0;
int i = -1;
public boolean hasNext() {
return n < size;
}
public int next() throws NoSuchElementException {
while (++i < used.length) {
if (used[i]) {
n++;
return keys[i];
}
}
throw new NoSuchElementException();
}
};
}
public IteratorLong values() {
return new IteratorLong() {
int n = 0;
int i = -1;
public boolean hasNext() {
return n < size;
}
public long next() throws NoSuchElementException {
while (++i < used.length) {
if (used[i]) {
n++;
return values[i];
}
}
throw new NoSuchElementException();
}
};
}
public Iterator entries() {
return new Iterator() {
int n = 0;
int i = -1;
public boolean hasNext() {
return n < size;
}
public Entry next() throws NoSuchElementException {
while (++i < used.length) {
if (used[i]) {
n++;
return new Entry() {
public int getKey() {
return keys[i];
}
public long getValue() {
return values[i];
}
};
}
}
throw new NoSuchElementException();
}
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
};
}
public long[] getAllValues() {
long[] a = new long[size];
int index = 0;
for (int ii = 0; ii < values.length; ii++) {
if (used[ii]) a[index++] = values[ii];
}
return a;
}
private void init(int initialCapacity) {
capacity = PrimeFinder.findNextPrime(initialCapacity);
step = Math.max(1, PrimeFinder.findPrevPrime(initialCapacity / 3));
limit = (int) (capacity * 0.75);
clear();
keys = new int[capacity];
values = new long[capacity];
}
private void resize(int newCapacity) {
int oldSize = size;
boolean[] oldUsed = used;
int[] oldKeys = keys;
long[] oldValues = values;
init(newCapacity);
int key, hash;
for (int i = 0; i < oldUsed.length; i++) {
if (oldUsed[i]) {
key = oldKeys[i];
hash = (key & Integer.MAX_VALUE) % capacity;
while (used[hash]) {
hash = (hash + step) % capacity;
}
used[hash] = true;
keys[hash] = key;
values[hash] = oldValues[i];
}
}
size = oldSize;
}
}