All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.mat.collect.HashMapIntLong Maven / Gradle / Ivy

There is a newer version: 2.1
Show newest version
/**
 * ****************************************************************************
 * 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;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy