public class XByteLinkedHashMap<V> extends Object implements XByteMap<V>
This class represents a hash map that avoid creation of garbage;
smooth capacity increase and thread-safe without external
synchronization when shared
.
XByteLinkedHashMap
has a predictable iteration order, which is the order in
which keys are inserted into the map (similar to
java.util.LinkedHashMap
collection class). If the map is
marked shared
then all operations are
thread-safe including iterations over the map's collections.
Unlike ConcurrentHashMap
, access
never
blocks; retrieval reflects the map state not older than the last time the
accessing threads have been synchronized (for multi-processors systems
synchronizing ensures that the CPU internal cache is not stale).
In most application it is not a problem because thread synchronization
is done at high level (e.g. scheduler) and threads run freely
(and quickly) until the next synchronization point. In some cases the
"happen before" guarantee is necessary (e.g. to ensure unicity) and
threads have to be synchronized explicitly. Whenever possible such
synchronization should be performed on the key object itself and
not the whole map. For example:[code]
XLinkedHashMap
XByteLinkedHashMap.Entry
can quickly be iterated over (forward or backward)
without using iterators. For example:[code]
XLinkedHashMap
Alternatively The map can be iterated over using reuseableEntryIterator()
,
reuseableKeyIterator()
, or reuseableValueIterator()
. Utilization of
these iterators does not introduce garbage because they are created once. However,
these iterators may not be used concurrently by multiple threads as they are
single instance by nature.
Custom map implementations may override the newEntry()
method
in order to return their own XByteLinkedHashMap.Entry
implementation (with
additional fields for example).
Shared
maps do not use internal synchronization, except in case of
concurrent 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 XLinkedHashMap
Implementation Note: To maintain time-determinism, rehash/resize is performed only when the map's size is small. 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).
This class was based on collections code from http://javolution.org, but modified for use outside of realtime jvms.
Modifier and Type | Class and Description |
---|---|
static class |
XByteLinkedHashMap.Entry<V>
This class represents a
XByteLinkedHashMap entry. |
Constructor and Description |
---|
XByteLinkedHashMap()
Creates a map whose capacity increment smoothly without large resize
operations.
|
XByteLinkedHashMap(int capacity)
Creates a map of specified maximum size (a full resize may occur if the
specififed capacity is exceeded).
|
XByteLinkedHashMap(XByteMap<? extends V> map)
Creates a map containing the specified entries, in the order they
are returned by the map iterator.
|
Modifier and Type | Method and Description |
---|---|
void |
clear()
Removes all map's entries.
|
boolean |
containsKey(byte key)
Indicates if this map contains a mapping for the specified key.
|
boolean |
containsValue(Object value)
Indicates if this map associates one or more keys to the specified value.
|
Set<XByteMap.Entry<V>> |
entrySet()
Returns a
XCollection view of the mappings contained in this
map. |
boolean |
equals(Object obj)
Compares the specified object with this map for equality.
|
V |
get(byte key)
Returns the value to which this map associates the specified key.
|
XByteLinkedHashMap.Entry<V> |
getEntry(byte key)
Returns the entry with the specified key.
|
int |
hashCode()
Returns the hash code value for this map.
|
XByteLinkedHashMap.Entry<V> |
head()
Returns the head entry of this map.
|
boolean |
isEmpty()
Indicates if this map contains no key-value mappings.
|
boolean |
isShared()
Indicates if this map supports concurrent operations without
synchronization (default unshared).
|
XByteSet |
keySet()
Returns a
XCollection view of the keys contained in this
map. |
static <V> XByteLinkedHashMap<V> |
newInstance()
Creates a new XLinkedHashMap.
|
void |
printStatistics(PrintStream out)
Prints the current statistics on this map.
|
V |
put(byte key,
V value)
Associates the specified value with the specified key in this map.
|
void |
putAll(XByteMap<? extends V> map)
Copies all of the mappings from the specified map to this map.
|
XByteLinkedHashMap.Entry<V> |
putEntry(byte key,
V value)
Associates the specified value with the specified key in this map and
returns the corresponding entry.
|
V |
putIfAbsent(byte key,
V value)
Associates the specified value only if the specified key is not already
associated.
|
V |
remove(byte key)
Removes the entry for the specified key if present.
|
XIterator<XByteMap.Entry<V>> |
reuseableEntryIterator()
Returns a reusable value iterator.
|
XByteIterator |
reuseableKeyIterator()
Returns a reusable key iterator.
|
XIterator<V> |
reuseableValueIterator()
Returns a reusable value iterator.
|
void |
setSupportsIteratorModifications(boolean allowed)
Can be called to change whether or not iterators support iterator modifications.
|
XByteLinkedHashMap<V> |
shared()
Sets the shared status of this map (whether the map is thread-safe
or not).
|
int |
size()
Returns the number of key-value mappings in this
XByteLinkedHashMap . |
XByteLinkedHashMap.Entry<V> |
tail()
Returns the tail entry of this map.
|
String |
toString()
Returns a string representation of this map.
|
XByteMap<V> |
unmodifiable()
Returns the unmodifiable view associated to this map.
|
Collection<V> |
values()
Returns a
XCollection view of the values contained in this
map. |
public XByteLinkedHashMap()
public XByteLinkedHashMap(int capacity)
capacity
- the maximum capacity.public void setSupportsIteratorModifications(boolean allowed)
allowed
- True if iterators should allow modifications.public static <V> XByteLinkedHashMap<V> newInstance()
public final XByteLinkedHashMap.Entry<V> head()
head().getNext()
holds
the first map entry.public final XByteLinkedHashMap.Entry<V> tail()
tail().getPrevious()
holds the last map entry.public final int size()
XByteLinkedHashMap
.
Note: If concurrent updates are performed, application should not rely upon the size during iterations.
size
in interface XByteMap<V>
Map.size()
public final boolean isEmpty()
isEmpty
in interface XByteMap<V>
true
if this map contains no key-value mappings;
false
otherwise.Map.isEmpty()
public final boolean containsKey(byte key)
containsKey
in interface XByteMap<V>
key
- the key whose presence in this map is to be tested.true
if this map contains a mapping for the
specified key; false
otherwise.NullPointerException
- if the key is null
.Map.containsKey(Object)
public final boolean containsValue(Object value)
containsValue
in interface XByteMap<V>
value
- the value whose presence in this map is to be tested.true
if this map maps one or more keys to the
specified value.NullPointerException
- if the key is null
.Map.containsValue(Object)
public final V get(byte key)
shared
.get
in interface XByteMap<V>
key
- the key whose associated value is to be returned.null
if there is no mapping for the key.NullPointerException
- if key is null
.Map.get(Object)
public final XByteLinkedHashMap.Entry<V> getEntry(byte key)
key
- the key whose associated entry is to be returned.null
if none.public final V put(byte key, V value)
shared
map, internal synchronization
is performed only when new entries are created.put
in interface XByteMap<V>
key
- the key with which the specified value is to be associated.value
- the value to be associated with the specified key.null
if there was no mapping for key. A
null
return can also indicate that the map
previously associated null
with the specified key.NullPointerException
- if the key is null
.Map.put(Object, Object)
public final XByteLinkedHashMap.Entry<V> putEntry(byte key, V value)
key
- the key with which the specified value is to be associated.value
- the value to be associated with the specified key.NullPointerException
- if the key is null
.public final void putAll(XByteMap<? extends V> map)
putAll
in interface XByteMap<V>
map
- the mappings to be stored in this map.NullPointerException
- the specified map is null
,
or the specified map contains null
keys.public final V putIfAbsent(byte key, V value)
key
- the key with which the specified value is to be associated.value
- the value to be associated with the specified key.null
if there was no mapping for key. A
null
return can also indicate that the map
previously associated null
with the specified key.NullPointerException
- if the key is null
.public final V remove(byte key)
shared
;
otherwise the entry is candidate for garbage collection.
Note: Shared maps in ImmortalMemory (e.g. static) should not remove
their entries as it could cause a memory leak (ImmortalMemory
is never garbage collected), instead they should set their
entry values to null
.
remove
in interface XByteMap<V>
key
- the key whose mapping is to be removed from the map.null
if there was no mapping for key. A
null
return can also indicate that the map
previously associated null
with the specified key.NullPointerException
- if the key is null
.public XByteLinkedHashMap<V> shared()
Sets the shared status of this map (whether the map is thread-safe or not). Shared maps are typically used for lookup table (e.g. static instances in ImmortalMemory). They support concurrent access (e.g. iterations) without synchronization, the maps updates themselves are synchronized internally.
Unlike ConcurrentHashMap
access to a shared map never
blocks. Retrieval reflects the map state not older than the last
time the accessing thread has been synchronized (for multi-processors
systems synchronizing ensures that the CPU internal cache is not
stale).
this
public boolean isShared()
true
if this map is thread-safe; false
otherwise.public final void clear()
shared
in which case the entries
are candidate for garbage collection.
Note: Shared maps in ImmortalMemory (e.g. static) should not remove
their entries as it could cause a memory leak (ImmortalMemory
is never garbage collected), instead they should set their
entry values to null
.
public boolean equals(Object obj)
true
if the given object is also a map and the two
maps represent the same mappings (regardless of collection iteration
order).public int hashCode()
public String toString()
String.valueOf(Object)
.public void printStatistics(PrintStream out)
out
- the stream to use for output (e.g. System.out
)public final Collection<V> values()
XCollection
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 element removal, which removes the corresponding mapping from
this map, via the Iterator.remove
,
Collection.remove
, removeAll
,
retainAll
and clear
operations.
It does not support the add
or addAll
operations.values
in interface XByteMap<V>
XCollection
).public final Set<XByteMap.Entry<V>> entrySet()
XCollection
view of the mappings contained in this
map. Each element in the returned collection is a
XLinkedHashMap.Entry
. The collection is backed by the map, so
changes to the map are reflected in the collection, and vice-versa. The
collection supports element removal, which removes the corresponding
mapping from this map, via the Iterator.remove
,
Collection.remove
,removeAll
,
retainAll
, and clear
operations. It does
not support the add
or addAll
operations.entrySet
in interface XByteMap<V>
XCollection
).public final XByteSet keySet()
XCollection
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 element removal, which
removes the corresponding mapping from this map, via the
Iterator.remove
, Collection.remove
,removeAll,
retainAll
, and clear
operations. It does
not support the add
or addAll
operations.
keySet
in interface XByteMap<V>
XCollection
).public XByteIterator reuseableKeyIterator()
XCollectionIterator.toFirst()
is called by this method to reset it
to the beginning.reuseableKeyIterator
in interface XByteMap<V>
public XIterator<V> reuseableValueIterator()
XCollectionIterator.toFirst()
is called by this method to reset it
to the beginning.reuseableValueIterator
in interface XByteMap<V>
public XIterator<XByteMap.Entry<V>> reuseableEntryIterator()
XCollectionIterator.toFirst()
is called by this method to reset it
to the beginning.reuseableEntryIterator
in interface XByteMap<V>
public final XByteMap<V> unmodifiable()
unmodifiable().entrySet()
)
result in an UnsupportedOperationException
being thrown.
Unmodifiable XCollection
views of this map keys and values
are nonetheless obtainable (e.g. unmodifiable().keySet(),
unmodifiable().values()
).
Copyright © 2019 Neeve Research, LLC. All Rights Reserved.