synchronized(index) { // javolution.util.Index instances are unique. sparseVector.put(index, value); } ... // Get synchronized(index) { // Blocking only when accessing the same index. value = sparseVector.get(index); // Latest value guaranteed. }[/code]
{@link FastMap} may use custom key comparators; the default comparator iseither {@link FastComparator#DIRECT DIRECT} or {@link FastComparator#REHASH REHASH} based upon the current Javolution Configuration. Users may explicitly set the key comparator to {@link FastComparator#DIRECT DIRECT} for optimum performancewhen the hash codes are well distributed for all run-time platforms (e.g. calculated hash codes).
Custom key comparators are extremely useful for value retrieval when map's keys and argument keys are not of the same class (such as {@link String} and {@link javolution.text.Text Text} ( {@link FastComparator#LEXICAL LEXICAL})), to substitute more efficient hash code calculations ( {@link FastComparator#STRING STRING}) or for identity maps ( {@link FastComparator#IDENTITY IDENTITY}):[code] FastMap identityMap = new FastMap().setKeyComparator(FastComparator.IDENTITY); [/code]
{@link FastMap.Entry} can quickly be iterated over (forward or backward)without using iterators. For example:[code] FastMap map = ...; for (FastMap.Entry e = map.head(), end = map.tail(); (e = e.getNext()) != end;) { String key = e.getKey(); // No typecast necessary. Thread value = e.getValue(); // No typecast necessary. }[/code]
Custom map implementations may override the {@link #newEntry} method in order to return their own {@link Entry} implementation (with additional fields for example).
{@link FastMap} are {@link Reusable reusable}; they maintain an internal pool of Map.Entry
objects. When an entry is removed from a map, it is automatically restored to its pool. Any new entry is allocated in the same memory area as the map itself (RTSJ). If the map is shared, removed entries are not recycled but only dereferenced (to maintain thread-safety)
{@link #shared() Shared} maps do not use internal synchronization, except in case ofconcurrent modifications of the map structure (entries being added/deleted). Reads and iterations are never synchronized and never blocking. With regards to the memory model, shared maps are equivalent to shared non-volatile variables (no "happen before" guarantee). They can be used as very efficient lookup tables. For example:[code] public class Unit { static FastMap labels = new FastMap().shared(); ... public String toString() { String label = labels.get(this); // No synchronization. if (label != null) return label; label = makeLabel(); labels.put(this, label); return label; } }[/code]
Implementation Note: To maintain time-determinism, rehash/resize is performed only when the map's size is small (see chart). For large maps (size > 512), the map is divided recursively into (64) smaller sub-maps. The cost of the dispatching (based upon hashcode value) has been measured to be at most 20% of the access time (and most often way less).
@author
Jean-Marie Dautelle
@version 5.2, September 11, 2007