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

javolution.util.FastMap Maven / Gradle / Ivy

Go to download

Only the Java Core part of Javolution library, with slight modifications for use in MSFTBX.

The newest version!
/*
 * 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;

import static javolution.lang.Realtime.Limit.CONSTANT;
import static javolution.lang.Realtime.Limit.LINEAR;

import java.io.IOException;
import java.io.Serializable;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;

import javolution.lang.Parallelizable;
import javolution.lang.Realtime;
import javolution.text.Cursor;
import javolution.text.DefaultTextFormat;
import javolution.text.TextContext;
import javolution.text.TextFormat;
import javolution.util.function.Consumer;
import javolution.util.function.Equalities;
import javolution.util.function.Equality;
import javolution.util.internal.map.AtomicMapImpl;
import javolution.util.internal.map.FastMapImpl;
import javolution.util.internal.map.ParallelMapImpl;
import javolution.util.internal.map.SequentialMapImpl;
import javolution.util.internal.map.SharedMapImpl;
import javolution.util.internal.map.UnmodifiableMapImpl;
import javolution.util.service.CollectionService;
import javolution.util.service.MapService;

/**
 * 

A high-performance hash map with {@link Realtime real-time} behavior. * Related to {@link FastCollection}, fast map supports various views. *

    *
  • {@link #atomic} - Thread-safe view for which all reads are mutex-free * and map updates (e.g. {@link #putAll putAll}) are atomic.
  • *
  • {@link #shared} - View allowing concurrent modifications.
  • *
  • {@link #parallel} - A view allowing parallel processing including {@link #update updates}.
  • *
  • {@link #sequential} - View disallowing parallel processing.
  • *
  • {@link #unmodifiable} - View which does not allow any modifications.
  • *
  • {@link #entrySet} - {@link FastSet} view over the map entries allowing * entries to be added/removed.
  • *
  • {@link #keySet} - {@link FastSet} view over the map keys allowing keys * to be added (map entry with {@code null} value).
  • *
  • {@link #values} - {@link FastCollection} view over the map values (add not supported).
  • *
*

The iteration order over the map keys, values or entries is deterministic * (unlike {@link java.util.HashMap}). It is either the insertion order (default) * or the key order for the {@link FastSortedMap} subclass. * This class permits {@code null} keys.

* *

Fast maps can advantageously replace any of the standard java.util maps.

* [code] * FastMap hashMap = new FastMap(); * FastMap concurrentHashMap = new FastMap().shared(); // FastMap implements ConcurrentMap interface. * FastMap linkedHashMap = new FastMap(); // Deterministic iteration order (insertion order). * FastMap treeMap = new FastSortedMap(); * FastMap concurrentSkipListMap = new FastSortedMap().shared(); * FastMap identityHashMap = new FastMap(Equalities.IDENTITY);[/code]

*

and adds more ... * [code] * FastMap atomicMap = new FastMap().atomic(); // Mutex-free access, all updates (e.g. putAll) atomics (unlike ConcurrentHashMap). * FastMap atomicTree = new FastSortedMap().atomic(); // Mutex-free access, all updates (e.g. putAll) atomics. * FastMap parallelMap = new FastMap().parallel(); // Map actions (perform/update) performed concurrently. * FastMap linkedConcurrentHashMap = new FastMap().shared(); // No equivalent in java.util ! * FastMap lexicalHashMap = new FastMap(Equalities.LEXICAL); // Allows for value retrieval using any CharSequence key. * FastMap fastStringHashMap = new FastMap(Equalities.LEXICAL_FAST); // Same with faster hashcode calculations. * ...[/code]

* *

Of course all views (entry, key, values) over a fast map are fast collections * and allow parallel processing. * [code] * Consumer> removeNull = new Consumer>() { * public void accept(Collection view) { * Iterator it = view.iterator(); * while (it.hasNext()) { * if (it.next() == null) it.remove(); * } * } * }; * FastMap names = ... * names.values().update(removeNull); // Remove all entries with null values. * names.atomic().values().update(removeNull); // Same but performed atomically. * names.parallel().values().update(removeNull); // Same but performed in parallel. * [/code]

* * @author Jean-Marie Dautelle * @version 6.0, July 21, 2013 */ @Realtime @DefaultTextFormat(FastMap.Text.class) public class FastMap implements Map, ConcurrentMap, Serializable { private static final long serialVersionUID = 0x600L; // Version. /** * Holds the actual map service implementation. */ private final MapService service; /** * Returns a new map holding the same entries as the specified * map (convenience method). */ public static FastMap of(Map that) { FastMap map = new FastMap(); map.putAll(that); return map; } /** * Creates an empty fast map. */ public FastMap() { this(Equalities.STANDARD); } /** * Creates an empty fast map using the specified comparator for keys * equality. */ public FastMap(Equality keyEquality) { this(keyEquality, Equalities.STANDARD); } /** * Creates an empty fast map using the specified comparators for keys * equality and values equality. */ public FastMap(Equality keyEquality, Equality valueEquality) { service = new FastMapImpl(keyEquality, valueEquality); } /** * Creates a map backed up by the specified service implementation. */ protected FastMap(MapService service) { this.service = service; } //////////////////////////////////////////////////////////////////////////// // Views. // /** * Returns an atomic view over this map. All operations that write * or access multiple elements in the map (such as putAll(), * keySet().retainAll(), ...) are atomic. * Iterators on atomic collections are thread-safe * (no {@link ConcurrentModificationException} possible). */ @Parallelizable(mutexFree = true, comment = "Except for write operations, all read operations are mutex-free.") public FastMap atomic() { return new FastMap(new AtomicMapImpl(service)); } /** * Returns a thread-safe view over this map. The shared view * allows for concurrent read as long as there is no writer. * The default implementation is based on * readers-writers locks giving priority to writers. * Iterators on shared collections are thread-safe * (no {@link ConcurrentModificationException} possible). */ @Parallelizable(mutexFree = false, comment = "Use multiple-readers/single-writer lock.") public FastMap shared() { return new FastMap(new SharedMapImpl(service)); } /** * Returns a parallel map. Parallel maps affect closure-based operations * over the map or any of its views (entry, key, values, etc.), all others * operations behaving the same. Parallel maps do not require this map * to be thread-safe (internal synchronization). * * @see #perform(Consumer) * @see #update(Consumer) * @see FastCollection#parallel() */ public FastMap parallel() { return new FastMap(new ParallelMapImpl(service)); } /** * Returns a sequential view of this collection. Using this view, * all closure-based iterations are performed sequentially. */ public FastMap sequential() { return new FastMap(new SequentialMapImpl(service)); } /** * Returns an unmodifiable view over this map. Any attempt to * modify the map through this view will result into * a {@link java.lang.UnsupportedOperationException} being raised. */ public FastMap unmodifiable() { return new FastMap(new UnmodifiableMapImpl(service)); } /** * Returns a set view of the keys contained in this map. * The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. The set supports * adding new keys for which the corresponding entry value * is always {@code null}. */ public FastSet keySet() { return new FastSet(service.keySet()); } /** * Returns a collection view of the values contained in this map. * The collection is backed by the map, so changes to the map are * reflected in the collection, and vice-versa. The collection * supports removing values (hence entries) but not adding new values. */ public FastCollection values() { return new FastCollection() { private static final long serialVersionUID = 0x600L; // Version. private final CollectionService serviceValues = service.values(); @Override protected CollectionService service() { return serviceValues; } }; } /** * Returns a set view of the mappings contained in * this map. The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa. The set * support adding/removing entries. As far as the set is concerned, * two entries are considered equals if they have the same keys regardless * of their values. */ public FastSet> entrySet() { return new FastSet>(service.entrySet()); } //////////////////////////////////////////////////////////////////////////// // Closures operations. // /** * Executes the specified read-only action on this map. * That logic may be performed concurrently on sub-maps * if this map is {@link #parallel() parallel}. * * @param action the read-only action. * @throws UnsupportedOperationException if the action tries to update * this map. * @throws ClassCastException if the action type is not compatible with * this map (e.g. action on sorted map and this is a hash map). * @see #update(Consumer) */ @Realtime(limit = LINEAR) @SuppressWarnings("unchecked") public void perform(Consumer> action) { service().perform((Consumer>) action, service()); } /** * Executes the specified update action on this map. * That logic may be performed concurrently on sub-maps * if this map is {@link #parallel() parallel}. * For {@link #atomic() atomic} maps the update is atomic (either concurrent * readers see the full result of the action or nothing). * * @param action the update action. * @throws ClassCastException if the action type is not compatible with * this map (e.g. action on sorted map and this is a hash map). * @see #perform(Consumer) */ @Realtime(limit = LINEAR) @SuppressWarnings("unchecked") public void update(Consumer> action) { service().update((Consumer>) action, service()); } //////////////////////////////////////////////////////////////////////////// // Map Interface. // /** Returns the number of entries/keys/values in this map. */ @Override @Realtime(limit = CONSTANT) public int size() { return service.size(); } /** Indicates if this map is empty */ @Override @Realtime(limit = CONSTANT) public boolean isEmpty() { return service.isEmpty(); } /** Indicates if this map contains the specified key. */ @Override @Realtime(limit = CONSTANT) public boolean containsKey(Object key) { return service.containsKey(key); } /** Indicates if this map contains the specified value. */ @Override @Realtime(limit = LINEAR) public boolean containsValue(Object value) { return service.containsValue(value); } /** Returns the value for the specified key. */ @Override @Realtime(limit = CONSTANT) public V get(Object key) { return service.get(key); } /** Associates the specified value with the specified key. */ @Override @Realtime(limit = CONSTANT) public V put(K key, V value) { return service.put(key, value); } /** Adds the specified map entries to this map. */ @Override @Realtime(limit = LINEAR) public void putAll(Map that) { service.putAll(that); } /** Removes the entry for the specified key. */ @Override @Realtime(limit = CONSTANT) public V remove(Object key) { return service.remove(key); } /** Removes all this map's entries. */ @Override @Realtime(limit = CONSTANT) public void clear() { service.clear(); } //////////////////////////////////////////////////////////////////////////// // ConcurrentMap Interface. // /** Associates the specified value with the specified key only if the * specified key has no current mapping. */ @Override @Realtime(limit = CONSTANT) public V putIfAbsent(K key, V value) { return service.putIfAbsent(key, value); } /** Removes the entry for a key only if currently mapped to a given value. */ @Override @Realtime(limit = CONSTANT) public boolean remove(Object key, Object value) { return service.remove(key, value); } /** Replaces the entry for a key only if currently mapped to a given value. */ @Override @Realtime(limit = CONSTANT) public boolean replace(K key, V oldValue, V newValue) { return service.replace(key, oldValue, newValue); } /** Replaces the entry for a key only if currently mapped to some value. */ @Override @Realtime(limit = CONSTANT) public V replace(K key, V value) { return service.replace(key, value); } //////////////////////////////////////////////////////////////////////////// // Misc. // /** * Returns this map with the specified [key, value] entry added. * This method allow for chaining. */ public FastMap add(K key, V value) { put(key, value); return this; } /** * Compares the specified object with this map for equality. * This method follows the {@link Map#equals(Object)} specification * regardless of the map's comparators. * * @param obj the object to be compared for equality with this map * @return true if this map is considered equals to the * one specified; false otherwise. */ @Override @Realtime(limit = LINEAR) public boolean equals(Object obj) { return service.equals(obj); } @Override public int hashCode() { return service.hashCode(); } /** * Returns the string representation of this map using its * {@link TextContext contextual format}. */ @Override @Realtime(limit = LINEAR) public String toString() { return TextContext.getFormat(FastMap.class).format(this); } /** * Returns this map service implementation. */ protected MapService service() { return service; } /** * Default text format for fast maps (parsing not supported). */ @Parallelizable public static class Text extends TextFormat> { @Override public FastMap parse(CharSequence csq, Cursor cursor) throws IllegalArgumentException { throw new UnsupportedOperationException(); } @Override public Appendable format(FastMap that, final Appendable dest) throws IOException { Iterator i = that.entrySet().iterator(); dest.append('{'); while (i.hasNext()) { Map.Entry entry = (Map.Entry) i.next(); TextContext.format(entry.getKey(), dest); dest.append('='); TextContext.format(entry.getValue(), dest); if (i.hasNext()) { dest.append(',').append(' '); } } return dest.append('}'); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy