mirror of https://github.com/apache/cassandra
remove dead Fast* classes
git-svn-id: https://svn.apache.org/repos/asf/incubator/cassandra/trunk@887544 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b8c65fadeb
commit
fb2cbc8922
|
|
@ -1,399 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.cassandra.utils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
/**
|
||||
* Base class for hashtables that use open addressing to resolve collisions.
|
||||
*/
|
||||
|
||||
abstract public class FastHash implements Cloneable
|
||||
{
|
||||
/** the current number of occupied slots in the hash. */
|
||||
protected transient int size_;
|
||||
|
||||
/** the current number of free slots in the hash. */
|
||||
protected transient int free_;
|
||||
|
||||
/** the load above which rehashing occurs. */
|
||||
protected static final float DEFAULT_LOAD_FACTOR = 0.5f;
|
||||
|
||||
/**
|
||||
* the default initial capacity for the hash table. This is one less than a
|
||||
* prime value because one is added to it when searching for a prime
|
||||
* capacity to account for the free slot required by open addressing. Thus,
|
||||
* the real default capacity is 11.
|
||||
*/
|
||||
protected static final int DEFAULT_INITIAL_CAPACITY = 10;
|
||||
|
||||
/**
|
||||
* Determines how full the internal table can become before rehashing is
|
||||
* required. This must be a value in the range: 0.0 < loadFactor < 1.0. The
|
||||
* default value is 0.5, which is about as large as you can get in open
|
||||
* addressing without hurting performance. Cf. Knuth, Volume 3., Chapter 6.
|
||||
*/
|
||||
protected float loadFactor_;
|
||||
|
||||
/**
|
||||
* The maximum number of elements allowed without allocating more space.
|
||||
*/
|
||||
protected int maxSize_;
|
||||
|
||||
/**
|
||||
* The number of removes that should be performed before an auto-compaction
|
||||
* occurs.
|
||||
*/
|
||||
protected int autoCompactRemovesRemaining_;
|
||||
|
||||
/**
|
||||
* The auto-compaction factor for the table.
|
||||
*
|
||||
* @see #setAutoCompactionFactor
|
||||
*/
|
||||
protected float autoCompactionFactor_;
|
||||
|
||||
/**
|
||||
* @see
|
||||
*/
|
||||
private boolean autoCompactTemporaryDisable_ = false;
|
||||
|
||||
/**
|
||||
* Creates a new <code>THash</code> instance with the default capacity and
|
||||
* load factor.
|
||||
*/
|
||||
public FastHash()
|
||||
{
|
||||
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>THash</code> instance with a prime capacity at or
|
||||
* near the specified capacity and with the default load factor.
|
||||
*
|
||||
* @param initialCapacity
|
||||
* an <code>int</code> value
|
||||
*/
|
||||
public FastHash(int initialCapacity)
|
||||
{
|
||||
this(initialCapacity, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>THash</code> instance with a prime capacity at or
|
||||
* near the minimum needed to hold <tt>initialCapacity</tt> elements with
|
||||
* load factor <tt>loadFactor</tt> without triggering a rehash.
|
||||
*
|
||||
* @param initialCapacity
|
||||
* an <code>int</code> value
|
||||
* @param loadFactor
|
||||
* a <code>float</code> value
|
||||
*/
|
||||
public FastHash(int initialCapacity, float loadFactor)
|
||||
{
|
||||
super();
|
||||
loadFactor_ = loadFactor;
|
||||
|
||||
// Through testing, the load factor (especially the default load factor)
|
||||
// has been
|
||||
// found to be a pretty good starting auto-compaction factor.
|
||||
autoCompactionFactor_ = loadFactor;
|
||||
|
||||
setUp((int) Math.ceil(initialCapacity / loadFactor));
|
||||
}
|
||||
|
||||
public Object clone()
|
||||
{
|
||||
try
|
||||
{
|
||||
return super.clone();
|
||||
}
|
||||
catch (CloneNotSupportedException cnse)
|
||||
{
|
||||
return null; // it's supported
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether this set is currently holding any elements.
|
||||
*
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return 0 == size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of distinct elements in this collection.
|
||||
*
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
public int size()
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current physical capacity of the hash table.
|
||||
*/
|
||||
abstract protected int capacity();
|
||||
|
||||
/**
|
||||
* Ensure that this hashtable has sufficient capacity to hold
|
||||
* <tt>desiredCapacity<tt> <b>additional</b> elements without
|
||||
* requiring a rehash. This is a tuning method you can call
|
||||
* before doing a large insert.
|
||||
*
|
||||
* @param desiredCapacity an <code>int</code> value
|
||||
*/
|
||||
public void ensureCapacity(int desiredCapacity)
|
||||
{
|
||||
if (desiredCapacity > (maxSize_ - size()))
|
||||
{
|
||||
rehash(PrimeFinder.nextPrime((int) Math.ceil(desiredCapacity
|
||||
+ size() / loadFactor_) + 1));
|
||||
computeMaxSize(capacity());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses the hashtable to the minimum prime size (as defined by
|
||||
* PrimeFinder) that will hold all of the elements currently in the table.
|
||||
* If you have done a lot of <tt>remove</tt> operations and plan to do a
|
||||
* lot of queries or insertions or iteration, it is a good idea to invoke
|
||||
* this method. Doing so will accomplish two things:
|
||||
*
|
||||
* <ol>
|
||||
* <li> You'll free memory allocated to the table but no longer needed
|
||||
* because of the remove()s.</li>
|
||||
*
|
||||
* <li> You'll get better query/insert/iterator performance because there
|
||||
* won't be any <tt>REMOVED</tt> slots to skip over when probing for
|
||||
* indices in the table.</li>
|
||||
* </ol>
|
||||
*/
|
||||
public void compact()
|
||||
{
|
||||
// need at least one free spot for open addressing
|
||||
rehash(PrimeFinder.nextPrime((int) Math.ceil(size() / loadFactor_) + 1));
|
||||
computeMaxSize(capacity());
|
||||
|
||||
// If auto-compaction is enabled, re-determine the compaction interval
|
||||
if (autoCompactionFactor_ != 0)
|
||||
{
|
||||
computeNextAutoCompactionAmount(size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The auto-compaction factor controls whether and when a table performs a
|
||||
* {@link #compact} automatically after a certain number of remove
|
||||
* operations. If the value is non-zero, the number of removes that need to
|
||||
* occur for auto-compaction is the size of table at the time of the
|
||||
* previous compaction (or the initial capacity) multiplied by this factor.
|
||||
* <p>
|
||||
* Setting this value to zero will disable auto-compaction.
|
||||
*/
|
||||
public void setAutoCompactionFactor(float factor)
|
||||
{
|
||||
if (factor < 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Factor must be >= 0: " + factor);
|
||||
}
|
||||
|
||||
autoCompactionFactor_ = factor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #setAutoCompactionFactor
|
||||
*/
|
||||
public float getAutoCompactionFactor()
|
||||
{
|
||||
return autoCompactionFactor_;
|
||||
}
|
||||
|
||||
/**
|
||||
* This simply calls {@link #compact compact}. It is included for symmetry
|
||||
* with other collection classes. Note that the name of this method is
|
||||
* somewhat misleading (which is why we prefer <tt>compact</tt>) as the
|
||||
* load factor may require capacity above and beyond the size of this
|
||||
* collection.
|
||||
*
|
||||
* @see #compact
|
||||
*/
|
||||
public final void trimToSize()
|
||||
{
|
||||
compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the record at <tt>index</tt>. Reduces the size of the
|
||||
* collection by one.
|
||||
*
|
||||
* @param index
|
||||
* an <code>int</code> value
|
||||
*/
|
||||
protected void removeAt(int index)
|
||||
{
|
||||
size_--;
|
||||
|
||||
// If auto-compaction is enabled, see if we need to compact
|
||||
if (autoCompactionFactor_ != 0)
|
||||
{
|
||||
autoCompactRemovesRemaining_--;
|
||||
|
||||
if (!autoCompactTemporaryDisable_
|
||||
&& autoCompactRemovesRemaining_ <= 0)
|
||||
{
|
||||
// Do the compact
|
||||
// NOTE: this will cause the next compaction interval to be
|
||||
// calculated
|
||||
compact();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the collection.
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
size_ = 0;
|
||||
free_ = capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
* initializes the hashtable to a prime capacity which is at least
|
||||
* <tt>initialCapacity + 1</tt>.
|
||||
*
|
||||
* @param initialCapacity
|
||||
* an <code>int</code> value
|
||||
* @return the actual capacity chosen
|
||||
*/
|
||||
protected int setUp(int initialCapacity)
|
||||
{
|
||||
int capacity;
|
||||
|
||||
capacity = PrimeFinder.nextPrime(initialCapacity);
|
||||
computeMaxSize(capacity);
|
||||
computeNextAutoCompactionAmount(initialCapacity);
|
||||
|
||||
return capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rehashes the set.
|
||||
*
|
||||
* @param newCapacity
|
||||
* an <code>int</code> value
|
||||
*/
|
||||
protected abstract void rehash(int newCapacity);
|
||||
|
||||
/**
|
||||
* Temporarily disables auto-compaction. MUST be followed by calling
|
||||
* {@link #reenableAutoCompaction}.
|
||||
*/
|
||||
protected void tempDisableAutoCompaction()
|
||||
{
|
||||
autoCompactTemporaryDisable_ = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-enable auto-compaction after it was disabled via
|
||||
* {@link #tempDisableAutoCompaction()}.
|
||||
*
|
||||
* @param check_for_compaction
|
||||
* True if compaction should be performed if needed before
|
||||
* returning. If false, no compaction will be performed.
|
||||
*/
|
||||
protected void reenableAutoCompaction(boolean check_for_compaction)
|
||||
{
|
||||
autoCompactTemporaryDisable_ = false;
|
||||
|
||||
if (check_for_compaction && autoCompactRemovesRemaining_ <= 0
|
||||
&& autoCompactionFactor_ != 0)
|
||||
{
|
||||
|
||||
// Do the compact
|
||||
// NOTE: this will cause the next compaction interval to be
|
||||
// calculated
|
||||
compact();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the values of maxSize. There will always be at least one free
|
||||
* slot required.
|
||||
*
|
||||
* @param capacity
|
||||
* an <code>int</code> value
|
||||
*/
|
||||
private final void computeMaxSize(int capacity)
|
||||
{
|
||||
// need at least one free slot for open addressing
|
||||
maxSize_ = Math.min(capacity - 1, (int) Math.floor(capacity
|
||||
* loadFactor_));
|
||||
free_ = capacity - size_; // reset the free element count
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the number of removes that need to happen before the next
|
||||
* auto-compaction will occur.
|
||||
*/
|
||||
private void computeNextAutoCompactionAmount(int size)
|
||||
{
|
||||
if (autoCompactionFactor_ != 0)
|
||||
{
|
||||
autoCompactRemovesRemaining_ = Math.round(size
|
||||
* autoCompactionFactor_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After an insert, this hook is called to adjust the size/free values of
|
||||
* the set and to perform rehashing if necessary.
|
||||
*/
|
||||
protected final void postInsertHook(boolean usedFreeSlot)
|
||||
{
|
||||
if (usedFreeSlot)
|
||||
{
|
||||
free_--;
|
||||
}
|
||||
|
||||
// rehash whenever we exhaust the available space in the table
|
||||
if (++size_ > maxSize_ || free_ == 0)
|
||||
{
|
||||
// choose a new capacity suited to the new state of the table
|
||||
// if we've grown beyond our maximum size, double capacity;
|
||||
// if we've exhausted the free spots, rehash to the same capacity,
|
||||
// which will free up any stale removed slots for reuse.
|
||||
int newCapacity = size_ > maxSize_ ? PrimeFinder
|
||||
.nextPrime(capacity() << 1) : capacity();
|
||||
rehash(newCapacity);
|
||||
computeMaxSize(capacity());
|
||||
}
|
||||
}
|
||||
|
||||
protected int calculateGrownCapacity()
|
||||
{
|
||||
return capacity() << 1;
|
||||
}
|
||||
}// THash
|
||||
|
|
@ -1,600 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.cassandra.utils;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* An implementation of the Map interface which uses an open addressed hash
|
||||
* table to store its contents
|
||||
*/
|
||||
public class FastHashMap<K, V> extends FastObjectHash<K> implements Map<K, V>, Serializable
|
||||
{
|
||||
static final long serialVersionUID = 1L;
|
||||
|
||||
/** the values of the map */
|
||||
protected transient V[] values_;
|
||||
|
||||
/**
|
||||
* Creates a new <code>FastHashMap</code> instance with the default capacity
|
||||
* and load factor.
|
||||
*/
|
||||
public FastHashMap()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>FastHashMap</code> instance with a prime capacity
|
||||
* equal to or greater than <tt>initialCapacity</tt> and with the default
|
||||
* load factor.
|
||||
*
|
||||
* @param initialCapacity
|
||||
* an <code>int</code> value
|
||||
*/
|
||||
public FastHashMap(int initialCapacity)
|
||||
{
|
||||
super(initialCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>FastHashMap</code> instance with a prime capacity
|
||||
* equal to or greater than <tt>initialCapacity</tt> and with the
|
||||
* specified load factor.
|
||||
*
|
||||
* @param initialCapacity
|
||||
* an <code>int</code> value
|
||||
* @param loadFactor
|
||||
* a <code>float</code> value
|
||||
*/
|
||||
public FastHashMap(int initialCapacity, float loadFactor)
|
||||
{
|
||||
super(initialCapacity, loadFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>FastHashMap</code> instance which contains the
|
||||
* key/value pairs in <tt>map</tt>.
|
||||
*
|
||||
* @param map
|
||||
* a <code>Map</code> value
|
||||
*/
|
||||
public FastHashMap(Map<K, V> map)
|
||||
{
|
||||
this(map.size());
|
||||
putAll(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a shallow clone of this collection
|
||||
*/
|
||||
public FastHashMap<K, V> clone()
|
||||
{
|
||||
FastHashMap<K, V> m = (FastHashMap<K, V>) super.clone();
|
||||
m.values_ = this.values_.clone();
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize the value array of the map.
|
||||
*
|
||||
* @param initialCapacity
|
||||
* an <code>int</code> value
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
protected int setUp(int initialCapacity)
|
||||
{
|
||||
int capacity;
|
||||
|
||||
capacity = super.setUp(initialCapacity);
|
||||
values_ = (V[]) new Object[capacity];
|
||||
return capacity;
|
||||
}
|
||||
|
||||
void addEntry(Object key, int index)
|
||||
{
|
||||
}
|
||||
|
||||
void removeEntry(Object key, int index)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a key/value pair into the map.
|
||||
*
|
||||
* @param key
|
||||
* an <code>Object</code> value
|
||||
* @param value
|
||||
* an <code>Object</code> value
|
||||
* @return the previous value associated with <tt>key</tt>, or null if
|
||||
* none was found.
|
||||
*/
|
||||
public V put(K key, V value)
|
||||
{
|
||||
V previous = null;
|
||||
Object oldKey;
|
||||
int index = insertionIndex(key);
|
||||
boolean isNewMapping = true;
|
||||
if (index < 0)
|
||||
{
|
||||
index = -index - 1;
|
||||
previous = values_[index];
|
||||
isNewMapping = false;
|
||||
}
|
||||
oldKey = set_[index];
|
||||
|
||||
if ( oldKey == FREE )
|
||||
{
|
||||
/* This is used as a hook to process new put() operations */
|
||||
addEntry(key, index);
|
||||
}
|
||||
|
||||
set_[index] = key;
|
||||
values_[index] = value;
|
||||
if (isNewMapping)
|
||||
{
|
||||
postInsertHook(oldKey == FREE);
|
||||
}
|
||||
|
||||
return previous;
|
||||
}
|
||||
|
||||
/**
|
||||
* rehashes the map to the new capacity.
|
||||
*
|
||||
* @param newCapacity
|
||||
* an <code>int</code> value
|
||||
*/
|
||||
protected void rehash(int newCapacity)
|
||||
{
|
||||
int oldCapacity = set_.length;
|
||||
Object oldKeys[] = set_;
|
||||
V oldVals[] = values_;
|
||||
|
||||
set_ = new Object[newCapacity];
|
||||
Arrays.fill(set_, FREE);
|
||||
values_ = (V[]) new Object[newCapacity];
|
||||
|
||||
for (int i = oldCapacity; i-- > 0;)
|
||||
{
|
||||
if (oldKeys[i] != FREE && oldKeys[i] != REMOVED)
|
||||
{
|
||||
Object o = oldKeys[i];
|
||||
int index = insertionIndex((K) o);
|
||||
if (index < 0)
|
||||
{
|
||||
throwObjectContractViolation(set_[(-index - 1)], o);
|
||||
}
|
||||
set_[index] = o;
|
||||
values_[index] = oldVals[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves the value for <tt>key</tt>
|
||||
*
|
||||
* @param key
|
||||
* an <code>Object</code> value
|
||||
* @return the value of <tt>key</tt> or null if no such mapping exists.
|
||||
*/
|
||||
public V get(Object key)
|
||||
{
|
||||
int index = index((K) key);
|
||||
return index < 0 ? null : values_[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties the map.
|
||||
*
|
||||
*/
|
||||
public void clear()
|
||||
{
|
||||
if (size() == 0)
|
||||
return; // optimization
|
||||
|
||||
super.clear();
|
||||
Object[] keys = set_;
|
||||
V[] vals = values_;
|
||||
|
||||
for (int i = keys.length; i-- > 0;)
|
||||
{
|
||||
keys[i] = FREE;
|
||||
vals[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a key/value pair from the map.
|
||||
*
|
||||
* @param key an <code>Object</code> value
|
||||
* @return an <code>Object</code> value
|
||||
*/
|
||||
public V remove(Object key)
|
||||
{
|
||||
V prev = null;
|
||||
int index = index((K)key);
|
||||
if (index >= 0)
|
||||
{
|
||||
prev = values_[index];
|
||||
/* clear key,state; adjust size */
|
||||
removeAt(index);
|
||||
/* This is used as hook to process deleted items */
|
||||
removeEntry(key, index);
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
* removes the mapping at <tt>index</tt> from the map.
|
||||
*
|
||||
* @param index an <code>int</code> value
|
||||
*/
|
||||
protected void removeAt(int index)
|
||||
{
|
||||
values_[index] = null;
|
||||
/* clear key, state; adjust size */
|
||||
super.removeAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view on the values of the map.
|
||||
*
|
||||
* @return a <code>Collection</code> value
|
||||
*/
|
||||
public Collection<V> values()
|
||||
{
|
||||
return Arrays.asList(values_);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a Set view on the keys of the map.
|
||||
*
|
||||
* @return a <code>Set</code> value
|
||||
*/
|
||||
public Set<K> keySet()
|
||||
{
|
||||
return new KeyView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Set view on the entries of the map.
|
||||
*
|
||||
* @return a <code>Set</code> value
|
||||
*/
|
||||
public Set<Map.Entry<K, V>> entrySet()
|
||||
{
|
||||
throw new UnsupportedOperationException(
|
||||
"This operation is currently not supported.");
|
||||
}
|
||||
|
||||
/**
|
||||
* checks for the presence of <tt>val</tt> in the values of the map.
|
||||
*
|
||||
* @param val
|
||||
* an <code>Object</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean containsValue(Object val)
|
||||
{
|
||||
Object[] set = set_;
|
||||
V[] vals = values_;
|
||||
|
||||
// special case null values so that we don't have to
|
||||
// perform null checks before every call to equals()
|
||||
if (null == val)
|
||||
{
|
||||
for (int i = vals.length; i-- > 0;)
|
||||
{
|
||||
if ((set[i] != FREE && set[i] != REMOVED) && val == vals[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = vals.length; i-- > 0;)
|
||||
{
|
||||
if ((set[i] != FREE && set[i] != REMOVED)
|
||||
&& (val == vals[i] || val.equals(vals[i])))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // end of else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks for the present of <tt>key</tt> in the keys of the map.
|
||||
*
|
||||
* @param key
|
||||
* an <code>Object</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean containsKey(Object key)
|
||||
{
|
||||
return contains(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* copies the key/value mappings in <tt>map</tt> into this map.
|
||||
*
|
||||
* @param map
|
||||
* a <code>Map</code> value
|
||||
*/
|
||||
public void putAll(Map<? extends K, ? extends V> map)
|
||||
{
|
||||
ensureCapacity(map.size());
|
||||
// could optimize this for cases when map instanceof FastHashMap
|
||||
for (Iterator<? extends Map.Entry<? extends K, ? extends V>> i = map
|
||||
.entrySet().iterator(); i.hasNext();)
|
||||
{
|
||||
Map.Entry<? extends K, ? extends V> e = i.next();
|
||||
put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class MapBackedView<E> extends AbstractSet<E> implements Set<E>, Iterable<E>
|
||||
{
|
||||
public abstract Iterator<E> iterator();
|
||||
public abstract boolean removeElement(E key);
|
||||
public abstract boolean containsElement(E key);
|
||||
|
||||
public boolean contains(Object key)
|
||||
{
|
||||
return containsElement((E) key);
|
||||
}
|
||||
|
||||
public boolean remove(Object o)
|
||||
{
|
||||
return removeElement((E) o);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection<?> collection)
|
||||
{
|
||||
for (Iterator i = collection.iterator(); i.hasNext();)
|
||||
{
|
||||
if (!contains(i.next()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
FastHashMap.this.clear();
|
||||
}
|
||||
|
||||
public boolean add(E obj)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return FastHashMap.this.size();
|
||||
}
|
||||
|
||||
public Object[] toArray()
|
||||
{
|
||||
Object[] result = new Object[size()];
|
||||
Iterator e = iterator();
|
||||
for (int i = 0; e.hasNext(); i++)
|
||||
result[i] = e.next();
|
||||
return result;
|
||||
}
|
||||
|
||||
public <T> T[] toArray(T[] a)
|
||||
{
|
||||
int size = size();
|
||||
if (a.length < size)
|
||||
a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
|
||||
|
||||
Iterator<E> it = iterator();
|
||||
Object[] result = a;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
result[i] = it.next();
|
||||
}
|
||||
|
||||
if (a.length > size)
|
||||
{
|
||||
a[size] = null;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return FastHashMap.this.isEmpty();
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends E> collection)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> collection)
|
||||
{
|
||||
boolean changed = false;
|
||||
Iterator i = iterator();
|
||||
while (i.hasNext())
|
||||
{
|
||||
if (!collection.contains(i.next()))
|
||||
{
|
||||
i.remove();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
}
|
||||
|
||||
protected class FastHashMapIterator<T> implements Iterator<T>
|
||||
{
|
||||
private int nextIndex_;
|
||||
private int expectedSize_;
|
||||
private FastObjectHash<T> tMap_;
|
||||
|
||||
FastHashMapIterator(FastObjectHash<T> tMap)
|
||||
{
|
||||
nextIndex_ = -1;
|
||||
expectedSize_ = tMap.size();
|
||||
tMap_ = tMap;
|
||||
}
|
||||
|
||||
public boolean hasNext()
|
||||
{
|
||||
return (expectedSize_ > 0);
|
||||
}
|
||||
|
||||
public T next()
|
||||
{
|
||||
moveToNextIndex();
|
||||
int index = nextIndex_;
|
||||
/*
|
||||
* Decrement so that we can track how many
|
||||
* elements we have already looked at.
|
||||
*/
|
||||
--expectedSize_;
|
||||
return (T)tMap_.set_[index];
|
||||
}
|
||||
|
||||
private void moveToNextIndex()
|
||||
{
|
||||
int i = nextIndex_ + 1;
|
||||
for ( ; i < tMap_.set_.length; ++i )
|
||||
{
|
||||
if ( tMap_.set_[i].equals(FREE) || tMap_.set_[i].equals(REMOVED) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
nextIndex_ = i;
|
||||
}
|
||||
|
||||
public void remove()
|
||||
{
|
||||
tMap_.removeAt(nextIndex_);
|
||||
--expectedSize_;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* a view onto the keys of the map.
|
||||
*/
|
||||
protected class KeyView extends MapBackedView<K>
|
||||
{
|
||||
public Iterator<K> iterator()
|
||||
{
|
||||
return new FastHashMapIterator(FastHashMap.this);
|
||||
}
|
||||
|
||||
public boolean removeElement(K key)
|
||||
{
|
||||
return null != FastHashMap.this.remove(key);
|
||||
}
|
||||
|
||||
public boolean containsElement(K key)
|
||||
{
|
||||
return FastHashMap.this.contains(key);
|
||||
}
|
||||
}
|
||||
|
||||
final class Entry implements Map.Entry<K, V>
|
||||
{
|
||||
private K key;
|
||||
private V val;
|
||||
private final int index;
|
||||
|
||||
Entry(final K key, V value, final int index)
|
||||
{
|
||||
this.key = key;
|
||||
this.val = value;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
void setKey(K aKey)
|
||||
{
|
||||
this.key = aKey;
|
||||
}
|
||||
|
||||
void setValue0(V aValue)
|
||||
{
|
||||
this.val = aValue;
|
||||
}
|
||||
|
||||
public K getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
public V getValue()
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
public V setValue(V o)
|
||||
{
|
||||
if (values_[index] != val)
|
||||
{
|
||||
throw new ConcurrentModificationException();
|
||||
}
|
||||
values_[index] = o;
|
||||
o = val; // need to return previous value
|
||||
val = o; // update this entry's value, in case
|
||||
// setValue is called again
|
||||
return o;
|
||||
}
|
||||
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o instanceof Map.Entry)
|
||||
{
|
||||
Map.Entry e1 = this;
|
||||
Map.Entry e2 = (Map.Entry) o;
|
||||
return (e1.getKey() == null ? e2.getKey() == null : e1.getKey().equals(e2.getKey()))
|
||||
&& (e1.getValue() == null ? e2.getValue() == null : e1.getValue().equals(e2.getValue()));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode());
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable
|
||||
{
|
||||
Map<String, String> map = new FastHashMap<String, String>();
|
||||
map.put("Avinash", "Avinash");
|
||||
map.put("Avinash", "Srinivas");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.cassandra.utils;
|
||||
|
||||
public class FastLinkedHashMap<K,V> extends FastHashMap<K,V>
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -1,322 +0,0 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.cassandra.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* An open addressed hashing implementation for Object types.
|
||||
*/
|
||||
abstract public class FastObjectHash<T> extends FastHash
|
||||
{
|
||||
static final long serialVersionUID = -3461112548087185871L;
|
||||
|
||||
/** the set of Objects */
|
||||
protected transient Object[] set_;
|
||||
protected static final Object REMOVED = new Object(), FREE = new Object();
|
||||
|
||||
/**
|
||||
* Creates a new <code>TObjectHash</code> instance with the default
|
||||
* capacity and load factor.
|
||||
*/
|
||||
public FastObjectHash()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>TObjectHash</code> instance whose capacity is the
|
||||
* next highest prime above <tt>initialCapacity + 1</tt> unless that value
|
||||
* is already prime.
|
||||
*
|
||||
* @param initialCapacity
|
||||
* an <code>int</code> value
|
||||
*/
|
||||
public FastObjectHash(int initialCapacity)
|
||||
{
|
||||
super(initialCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>TObjectHash</code> instance with a prime value at
|
||||
* or near the specified capacity and load factor.
|
||||
*
|
||||
* @param initialCapacity
|
||||
* used to find a prime capacity for the table.
|
||||
* @param loadFactor
|
||||
* used to calculate the threshold over which rehashing takes
|
||||
* place.
|
||||
*/
|
||||
public FastObjectHash(int initialCapacity, float loadFactor)
|
||||
{
|
||||
super(initialCapacity, loadFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a shallow clone of this collection
|
||||
*/
|
||||
public FastObjectHash<T> clone()
|
||||
{
|
||||
FastObjectHash<T> h = (FastObjectHash<T>) super.clone();
|
||||
h.set_ = (Object[]) this.set_.clone();
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked every time a key is
|
||||
* added into the Map.
|
||||
* @param key key that is inserted
|
||||
* @param index index position of the key being
|
||||
* inserted
|
||||
*/
|
||||
abstract void addEntry(Object key, int index);
|
||||
|
||||
/**
|
||||
* This method is invoked every time a key is
|
||||
* deleted from the Map.
|
||||
* @param key key being deleted
|
||||
* @param index index position of the key being
|
||||
* deleted
|
||||
*/
|
||||
abstract void removeEntry(Object key, int index);
|
||||
|
||||
protected int capacity()
|
||||
{
|
||||
return set_.length;
|
||||
}
|
||||
|
||||
protected void removeAt(int index)
|
||||
{
|
||||
set_[index] = REMOVED;
|
||||
super.removeAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* initializes the Object set of this hash table.
|
||||
*
|
||||
* @param initialCapacity
|
||||
* an <code>int</code> value
|
||||
* @return an <code>int</code> value
|
||||
*/
|
||||
protected int setUp(int initialCapacity)
|
||||
{
|
||||
int capacity;
|
||||
|
||||
capacity = super.setUp(initialCapacity);
|
||||
set_ = new Object[capacity];
|
||||
Arrays.fill(set_, FREE);
|
||||
return capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the set for <tt>obj</tt>
|
||||
*
|
||||
* @param obj
|
||||
* an <code>Object</code> value
|
||||
* @return a <code>boolean</code> value
|
||||
*/
|
||||
public boolean contains(Object obj)
|
||||
{
|
||||
return index((T) obj) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the index of <tt>obj</tt>.
|
||||
*
|
||||
* @param obj
|
||||
* an <code>Object</code> value
|
||||
* @return the index of <tt>obj</tt> or -1 if it isn't in the set.
|
||||
*/
|
||||
protected int index(Object obj)
|
||||
{
|
||||
final Object[] set = set_;
|
||||
final int length = set.length;
|
||||
final int hash = obj.hashCode() & 0x7fffffff;
|
||||
int index = hash % length;
|
||||
Object cur = set[index];
|
||||
|
||||
if (cur == FREE)
|
||||
return -1;
|
||||
|
||||
// NOTE: here it has to be REMOVED or FULL (some user-given value)
|
||||
if (cur == REMOVED || cur.equals(obj))
|
||||
{
|
||||
// see Knuth, p. 529
|
||||
final int probe = 1 + (hash % (length - 2));
|
||||
|
||||
while (cur != FREE&& (cur == REMOVED || !cur.equals(obj)))
|
||||
{
|
||||
index -= probe;
|
||||
if (index < 0)
|
||||
{
|
||||
index += length;
|
||||
}
|
||||
cur = set[index];
|
||||
}
|
||||
}
|
||||
|
||||
return cur == FREE ? -1 : index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the index at which <tt>obj</tt> can be inserted. if there is
|
||||
* already a value equal()ing <tt>obj</tt> in the set, returns that
|
||||
* value's index as <tt>-index - 1</tt>.
|
||||
*
|
||||
* @param obj
|
||||
* an <code>Object</code> value
|
||||
* @return the index of a FREE slot at which obj can be inserted or, if obj
|
||||
* is already stored in the hash, the negative value of that index,
|
||||
* minus 1: -index -1.
|
||||
*/
|
||||
protected int insertionIndex(T obj)
|
||||
{
|
||||
final Object[] set = set_;
|
||||
final int length = set.length;
|
||||
final int hash = obj.hashCode() & 0x7fffffff;
|
||||
int index = hash % length;
|
||||
Object cur = set[index];
|
||||
|
||||
if (cur == FREE)
|
||||
{
|
||||
return index; // empty, all done
|
||||
}
|
||||
else if (cur != REMOVED && cur.equals(obj))
|
||||
{
|
||||
return -index - 1; // already stored
|
||||
}
|
||||
else
|
||||
{ // already FULL or REMOVED, must probe
|
||||
// compute the double token
|
||||
final int probe = 1 + (hash % (length - 2));
|
||||
|
||||
// if the slot we landed on is FULL (but not removed), probe
|
||||
// until we find an empty slot, a REMOVED slot, or an element
|
||||
// equal to the one we are trying to insert.
|
||||
// finding an empty slot means that the value is not present
|
||||
// and that we should use that slot as the insertion point;
|
||||
// finding a REMOVED slot means that we need to keep searching,
|
||||
// however we want to remember the offset of that REMOVED slot
|
||||
// so we can reuse it in case a "new" insertion (i.e. not an update)
|
||||
// is possible.
|
||||
// finding a matching value means that we've found that our desired
|
||||
// key is already in the table
|
||||
if (cur != REMOVED)
|
||||
{
|
||||
// starting at the natural offset, probe until we find an
|
||||
// offset that isn't full.
|
||||
do
|
||||
{
|
||||
index -= probe;
|
||||
if (index < 0)
|
||||
{
|
||||
index += length;
|
||||
}
|
||||
cur = set[index];
|
||||
}
|
||||
while (cur != FREE && cur != REMOVED
|
||||
&& !cur.equals(obj));
|
||||
}
|
||||
|
||||
// if the index we found was removed: continue probing until we
|
||||
// locate a free location or an element which equal()s the
|
||||
// one we have.
|
||||
if (cur == REMOVED)
|
||||
{
|
||||
int firstRemoved = index;
|
||||
while (cur != FREE
|
||||
&& (cur == REMOVED || !cur.equals(obj)))
|
||||
{
|
||||
index -= probe;
|
||||
if (index < 0)
|
||||
{
|
||||
index += length;
|
||||
}
|
||||
cur = set[index];
|
||||
}
|
||||
// NOTE: cur cannot == REMOVED in this block
|
||||
return (cur != FREE) ? -index - 1 : firstRemoved;
|
||||
}
|
||||
// if it's full, the key is already stored
|
||||
// NOTE: cur cannot equal REMOVE here (would have returned already
|
||||
// (see above)
|
||||
return (cur != FREE) ? -index - 1 : index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the default implementation of TObjectHashingStrategy: it
|
||||
* delegates hashing to the Object's hashCode method.
|
||||
*
|
||||
* @param o
|
||||
* for which the hashcode is to be computed
|
||||
* @return the hashCode
|
||||
* @see Object#hashCode()
|
||||
*/
|
||||
public final int computeHashCode(T o)
|
||||
{
|
||||
return o == null ? 0 : o.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the default implementation of TObjectHashingStrategy: it
|
||||
* delegates equality comparisons to the first parameter's equals() method.
|
||||
*
|
||||
* @param o1
|
||||
* an <code>Object</code> value
|
||||
* @param o2
|
||||
* an <code>Object</code> value
|
||||
* @return true if the objects are equal
|
||||
* @see Object#equals(Object)
|
||||
*/
|
||||
public final boolean equals(T o1, T o2)
|
||||
{
|
||||
return o1 == null ? o2 == null : o1.equals(o2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience methods for subclasses to use in throwing exceptions about
|
||||
* badly behaved user objects employed as keys. We have to throw an
|
||||
* IllegalArgumentException with a rather verbose message telling the user
|
||||
* that they need to fix their object implementation to conform to the
|
||||
* general contract for java.lang.Object.
|
||||
*
|
||||
* @param o1
|
||||
* the first of the equal elements with unequal hash codes.
|
||||
* @param o2
|
||||
* the second of the equal elements with unequal hash codes.
|
||||
* @exception IllegalArgumentException
|
||||
* the whole point of this method.
|
||||
*/
|
||||
protected final void throwObjectContractViolation(Object o1, Object o2)
|
||||
throws IllegalArgumentException
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"Equal objects must have equal hashcodes. "
|
||||
+ "During rehashing, Trove discovered that "
|
||||
+ "the following two objects claim to be "
|
||||
+ "equal (as in java.lang.Object.equals()) "
|
||||
+ "but their hashCodes (or those calculated by "
|
||||
+ "your TObjectHashingStrategy) are not equal."
|
||||
+ "This violates the general contract of "
|
||||
+ "java.lang.Object.hashCode(). See bullet point two "
|
||||
+ "in that method's documentation. " + "object #1 ="
|
||||
+ o1 + "; object #2 =" + o2);
|
||||
}
|
||||
} // TObjectHash
|
||||
Loading…
Reference in New Issue