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

com.caucho.util.LongKeyHashMap Maven / Gradle / Ivy

There is a newer version: 4.0.66
Show newest version
/*
 * Copyright (c) 1998-2012 Caucho Technology -- all rights reserved
 *
 * This file is part of Resin(R) Open Source
 *
 * Each copy or derived work must preserve the copyright notice and this
 * notice unmodified.
 *
 * Resin Open Source is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Resin Open Source is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
 * of NON-INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Resin Open Source; if not, write to the
 *   Free SoftwareFoundation, Inc.
 *   59 Temple Place, Suite 330
 *   Boston, MA 02111-1307  USA
 *
 * @author Scott Ferguson
 */

package com.caucho.util;

import java.util.Iterator;

/**
 * Cache with a clock replacement policy.
 *
 * 

Null keys are not allowed. LruCache is synchronized. */ public class LongKeyHashMap { // array containing the keys private long []_keys; // array containing the values private E []_values; // number of items in the cache private int _size; private int _mask; /** * Create the clock cache with a specific capacity. * * @param initialCapacity minimum capacity of the cache */ public LongKeyHashMap() { this(8); } /** * Create the clock cache with a specific capacity. * * @param initialCapacity minimum capacity of the cache */ public LongKeyHashMap(int initialCapacity) { int capacity; for (capacity = 8; capacity < 2 * initialCapacity; capacity *= 2) { } _keys = new long[capacity]; _values = (E []) new Object[capacity]; _mask = capacity - 1; } /** * Returns the current number of entries in the cache. */ public int size() { return _size; } /** * Clears the map */ public void clear() { synchronized (this) { for (int i = 0; i < _values.length; i++) { _values[i] = null; } _size = 0; } } /** * Get an item from the cache and make it most recently used. * * @param key key to lookup the item * @return the matching object in the cache */ public E get(long key) { int hash = getHash(key); int count = _size + 1; synchronized (this) { for (; count > 0; count--) { E item = _values[hash]; if (item == null) return null; if (_keys[hash] == key) return item; hash = (hash + 1) & _mask; } } return null; } /** * Puts a new item in the cache. If the cache is full, remove the * LRU item. * * @param key key to store data * @param value value to be stored * * @return old value stored under the key */ public E put(long key, E value) { E item = putImpl(key, value); // forced resizing if 1/2 full if (_values.length <= 2 * _size) { synchronized (this) { long []oldKeys = _keys; E []oldValues = _values; _keys = new long[2 * oldKeys.length]; _values = (E []) new Object[2 * oldValues.length]; _mask = _values.length - 1; for (int i = oldValues.length - 1; i >= 0; i--) { long oldKey = oldKeys[i]; E oldValue = oldValues[i]; if (oldValue != null) putImpl(oldKey, oldValue); } } } return item; } /** * Implementation of the put. */ private E putImpl(long key, E value) { E item = null; int hash = getHash(key); int count = _size + 1; synchronized (this) { for (; count > 0; count--) { item = _values[hash]; // No matching item, so create one if (item == null) { _keys[hash] = key; _values[hash] = value; _size++; return null; } // matching item gets replaced if (_keys[hash] == key) { _values[hash] = value; return item; } hash = (hash + 1) & _mask; } } throw new IllegalStateException(); } /** * Removes an item from the map * * @param key the key to remove * * @return the value removed */ public E remove(long key) { int hash = getHash(key); int count = _size + 1; E item = null; synchronized (this) { for (; count > 0; count--) { item = _values[hash]; if (item == null) return null; if (_keys[hash] == key) { _values[hash] = null; _size--; refillEntries(hash); break; } hash = (hash + 1) & _mask; } } if (count < 0) throw new RuntimeException("internal cache error"); return item; } /** * Put the item in the best location available in the hash table. */ private void refillEntries(int hash) { for (int count = _size; count >= 0; count--) { hash = (hash + 1) & _mask; if (_values[hash] == null) return; _values[hash] = null; refillEntry(hash); } } /** * Put the item in the best location available in the hash table. */ private void refillEntry(int baseHash) { long key = _keys[baseHash]; E value = _values[baseHash]; int hash = getHash(key); for (int count = _size; count >= 0; count--) { if (_values[hash] == null) { _keys[hash] = key; _values[hash] = value; return; } hash = (hash + 1) & _mask; } } /** * Returns the key's hash */ private int getHash(long key) { long hash = key; hash = hash * 0x5deece66dl + 0xbl + (hash >>> 32) * 137; return (int) (hash) & _mask; } public Iterator valueIterator() { return new ValueIterator(); } class ValueIterator implements Iterator { private E []_values; private int _index; private E _value; ValueIterator() { _values = LongKeyHashMap.this._values; _index = -1; findNext(); } public boolean hasNext() { return _value != null; } public E next() { E value = _value; findNext(); return value; } public void remove() { } private void findNext() { _value = null; for (_index++; _index < _values.length; _index++) { _value = _values[_index]; if (_value != null) return; } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy