/*
* Javolution - Java(TM) Solution for Real-Time and Embedded Systems
* Copyright (C) 2012 - Javolution (http://javolution.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
package javolution.util.internal.map;
import java.util.Iterator;
import java.util.NoSuchElementException;
import javolution.util.function.Equality;
/**
* The default {@link javolution.util.FastMap FastMap} implementation
* based on {@link FractalMapImpl fractal maps}.
* This implementation ensures that no more than 3/4 of the map capacity is
* ever wasted.
*/
public class FastMapImpl<K, V> extends MapView<K, V> {
private static final long serialVersionUID = 0x600L; // Version.
transient MapEntryImpl<K, V> firstEntry = null;
transient FractalMapImpl fractal;
transient MapEntryImpl<K, V> freeEntry = new MapEntryImpl<K, V>();
final Equality<? super K> keyComparator;
transient MapEntryImpl<K, V> lastEntry = null;
transient int size;
final Equality<? super V> valueComparator;
@SuppressWarnings("unchecked")
public FastMapImpl(Equality<? super K> keyComparator,
final Equality<? super V> valueComparator) {
super(null); // Root.
this.keyComparator = keyComparator;
this.valueComparator = valueComparator;
fractal = new FractalMapImpl((Equality<Object>) keyComparator);
}
@SuppressWarnings("unchecked")
@Override
public void clear() {
firstEntry = null;
lastEntry = null;
fractal = new FractalMapImpl((Equality<Object>) keyComparator);
size = 0;
}
@Override
public FastMapImpl<K, V> clone() { // Makes a copy.
FastMapImpl<K, V> copy = new FastMapImpl<K, V>(keyComparator(),
valueComparator());
copy.putAll(this);
return copy;
}
@Override
public boolean containsKey(Object key) {
return fractal.getEntry(key) != null;
}
@SuppressWarnings("unchecked")
@Override
public V get(Object key) {
MapEntryImpl<K, V> entry = fractal.getEntry(key);
if (entry == null) return null;
return entry.value;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return new Iterator<Entry<K, V>>() {
MapEntryImpl<K, V> current;
MapEntryImpl<K, V> next = firstEntry;
@Override
public boolean hasNext() {
return (next != null);
}
@Override
public java.util.Map.Entry<K, V> next() {
if (next == null) throw new NoSuchElementException();
current = next;
next = next.next;
return current;
}
@Override
public void remove() {
if (current == null) throw new IllegalStateException();
fractal.removeEntry(current.key, current.hash);
detachEntry(current); // Entry is not referenced anymore and will be gc.
size--;
}
};
}
@Override
public Equality<? super K> keyComparator() {
return keyComparator;
}
@SuppressWarnings("unchecked")
@Override
public V put(K key, V value) {
MapEntryImpl<K, V> tmp = fractal.addEntry(freeEntry, key);
if (tmp == freeEntry) { // New entry.
freeEntry = new MapEntryImpl<K, V>();
attachEntry(tmp);
size++;
tmp.value = value;
return null;
} else { // Existing entry.
V oldValue = (V) tmp.value;
tmp.value = value;
return oldValue;
}
}
@SuppressWarnings("unchecked")
@Override
public V putIfAbsent(K key, V value) {
MapEntryImpl<K, V> tmp = fractal.addEntry(freeEntry, key);
if (tmp == freeEntry) { // New entry.
freeEntry = new MapEntryImpl<K, V>();
attachEntry(tmp);
size++;
tmp.value = value;
return null;
} else { // Existing entry.
return (V) tmp.value;
}
}
@SuppressWarnings("unchecked")
@Override
public V remove(Object key) {
MapEntryImpl<K, V> entry = fractal.removeEntry(key,
keyComparator.hashOf((K) key));
if (entry == null) return null;
detachEntry(entry); // Entry is not referenced anymore and will be gc.
size--;
return entry.value;
}
@SuppressWarnings("unchecked")
@Override
public boolean remove(Object key, Object value) {
MapEntryImpl<K, V> entry = fractal.getEntry(key);
if (entry == null) return false;
if (!valueComparator.equal((V) entry.value, (V) value)) return false;
fractal.removeEntry(key, entry.hash);
detachEntry(entry); // Entry is not referenced anymore and will be gc.
size--;
return true;
}
@SuppressWarnings("unchecked")
@Override
public V replace(K key, V value) {
MapEntryImpl<K, V> entry = fractal.getEntry(key);
if (entry == null) return null;
V oldValue = entry.value;
entry.value = value;
return oldValue;
}
@SuppressWarnings("unchecked")
@Override
public boolean replace(K key, V oldValue, V newValue) {
MapEntryImpl<K, V> entry = fractal.getEntry(key);
if (entry == null) return false;
if (!valueComparator.equal(entry.value, oldValue)) return false;
entry.value = newValue;
return true;
}
@Override
public int size() {
return size;
}
@Override
public Equality<? super V> valueComparator() {
return valueComparator;
}
private void attachEntry(MapEntryImpl<K, V> entry) {
if (lastEntry != null) {
lastEntry.next = entry;
entry.previous = lastEntry;
}
lastEntry = entry;
if (firstEntry == null) {
firstEntry = entry;
}
}
private void detachEntry(MapEntryImpl<K, V> entry) {
if (entry == firstEntry) {
firstEntry = entry.next;
}
if (entry == lastEntry) {
lastEntry = entry.previous;
}
MapEntryImpl<K, V> previous = entry.previous;
MapEntryImpl<K, V> next = entry.next;
if (previous != null) {
previous.next = next;
}
if (next != null) {
next.previous = previous;
}
}
/** For serialization support */
@SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject(); // Deserialize comparators.
fractal = new FractalMapImpl((Equality<Object>) keyComparator);
freeEntry = new MapEntryImpl<K, V>();
int n = s.readInt();
for (int i = 0; i < n; i++) {
put((K) s.readObject(), (V) s.readObject());
}
}
/** For serialization support */
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
s.defaultWriteObject(); // Serialize comparators.
s.writeInt(size);
Iterator<Entry<K, V>> it = iterator();
while (it.hasNext()) {
Entry<K, V> e = it.next();
s.writeObject(e.getKey());
s.writeObject(e.getValue());
}
}
}