Class AbstractKVNavigableMap<K,V>
- Type Parameters:
K
- key typeV
- value type
- All Implemented Interfaces:
Map<K,
,V> NavigableMap<K,
,V> SortedMap<K,
V>
- Direct Known Subclasses:
KVNavigableMap
NavigableMap
support superclass for maps backed by keys and values encoded as byte[]
arrays in a KVStore
, and whose key sort order is consistent with the byte[]
key encoding.
There must be an equivalence between map keys and byte[]
key encodings (i.e., there must be
only one valid encoding per map key).
Subclass Methods
Subclasses must implement the encodeKey(), decodeKey(),
and decodeValue() methods to convert keys and value to/from KVStore
keys and values,
and createSubMap()
to allow creating reversed and restricted range sub-maps.
Subclasses must also implement comparator()
, and the resulting sort order must be consistent with
the sort order of the encoded byte[]
keys (possibly reversed
).
This class provides a read-only implementation; for a mutable implementation, subclasses should also implement
put()
, remove()
, and AbstractMap.clear()
; note, these methods must verify the key
isVisible()
before making any changes.
Additional subclass notes:
navigableKeySet()
returns aSet
for which:entrySet()
returns aSet
for which:- The
add()
method is not supported. - The
remove()
method and theremove()
method of the associatedIterator
delegate to this instance'sremove()
method (but only when theMap.Entry
is still contained in the map). - The
Map.Entry
elements'setValue()
method delegates to this instance'sput()
method (but only when theMap.Entry
is still contained in the map). - The
clear()
method delegates to this instance'sAbstractMap.clear()
method.
- The
Prefix Mode
Instances support "prefix mode" where the byte[]
keys may have arbitrary trailing garbage, which is ignored,
and so by definition no key can be a prefix of any other key. The length of the prefix is determined implicitly by the
number of bytes produced by encodeKey()
or consumed by decodeKey()
.
When not in prefix mode, decodeKey()
must consume the entire key to preserve correct semantics.
Prefix mode can also be used when the map values (or some portion thereof) are contained in the key's "garbage" suffix.
The decodeValue()
takes a KVPair
so it can read from both the key and the value.
In particular, instances can be built from key/value data where all the values are empty.
Key Restrictions
Instances are configured with an (optional) KeyRange
; when range restriction is in
effect, this key range corresponds to the bounds.
Instances also support filtering visible keys using a KeyFilter
; see filterKeys()
.
To be isVisible(byte[]) in the map, keys must both be in the KeyRange
and pass the KeyFilter
.
Concurrent Modifications
This implementation never throws ConcurrentModificationException
; instead, iterators always
see the most up-to-date state of the associated KVStore
.
- See Also:
-
Nested Class Summary
Nested classes/interfaces inherited from class java.util.AbstractMap
AbstractMap.SimpleEntry<K extends Object,
V extends Object>, AbstractMap.SimpleImmutableEntry<K extends Object, V extends Object> -
Field Summary
Modifier and TypeFieldDescriptionprotected final KeyFilter
Key filter, or null if all keys in the range should be visible.protected final KeyRange
Key range, or null for the entire range.protected final KVStore
The underlyingKVStore
.protected final boolean
Whether we are in "prefix" mode.protected final boolean
Whether the ordering of this instance is reversed.Fields inherited from class io.permazen.util.AbstractNavigableMap
bounds
-
Constructor Summary
ModifierConstructorDescriptionprotected
AbstractKVNavigableMap
(KVStore kv, boolean prefixMode) Convenience constructor for when there are no range restrictions.protected
AbstractKVNavigableMap
(KVStore kv, boolean prefixMode, boolean reversed, KeyRange keyRange, KeyFilter keyFilter, Bounds<K> bounds) Internal constructor.protected
AbstractKVNavigableMap
(KVStore kv, boolean prefixMode, byte[] prefix) Convenience constructor for when the range of visibleKVStore
keys is all keys sharing a givenbyte[]
prefix.protected
AbstractKVNavigableMap
(KVStore kv, boolean prefixMode, KeyRange keyRange) Primary constructor. -
Method Summary
Modifier and TypeMethodDescriptionprotected abstract NavigableMap<K,
V> createSubMap
(boolean newReversed, KeyRange newKeyRange, KeyFilter newKeyFilter, Bounds<K> newBounds) Create a (possibly reversed) view of this instance with (possibly) tighter lower and/or upper bounds and the givenKeyFilter
, if any.protected final NavigableMap<K,
V> createSubMap
(boolean reverse, Bounds<K> newBounds) Create a (possibly reversed) view of this instance with (possibly) tighter lower and/or upper bounds.protected abstract K
decodeKey
(ByteReader reader) Decode a key object from an encodedbyte[]
key.protected abstract V
decodeValue
(KVPair pair) Decode a value object from an encodedbyte[]
key/value pair.protected abstract void
encodeKey
(ByteWriter writer, Object obj) Encode the given key object into abyte[]
key.protected byte[]
encodeVisibleKey
(Object obj, boolean fail) Encode the given key object, if possible, and verify the correspondingbyte[]
key is visible, otherwise return null or throw an exception.entrySet()
filterKeys
(KeyFilter keyFilter) Create a view of this instance with additional filtering applied to the underlyingbyte[]
keys.protected boolean
isVisible
(byte[] key) protected boolean
isWithinLowerBound
(K key) Determine if the given element is within this instance's lower bound (if any).protected boolean
isWithinUpperBound
(K key) Determine if the given element is within this instance's upper bound (if any).Methods inherited from class io.permazen.util.AbstractNavigableMap
ceilingEntry, ceilingKey, containsKey, descendingKeySet, descendingMap, firstEntry, firstKey, floorEntry, floorKey, getBounds, getComparator, headMap, headMap, higherEntry, higherKey, isEmpty, keySet, lastEntry, lastKey, lowerEntry, lowerKey, pollFirstEntry, pollLastEntry, remove, searchAbove, searchBelow, subMap, subMap, tailMap, tailMap
Methods inherited from class java.util.AbstractMap
clear, clone, containsValue, equals, hashCode, put, putAll, size, toString, values
Methods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, wait, wait, wait
Methods inherited from interface java.util.Map
clear, compute, computeIfAbsent, computeIfPresent, containsValue, equals, forEach, getOrDefault, hashCode, merge, put, putAll, putIfAbsent, remove, replace, replace, replaceAll, size
Methods inherited from interface java.util.SortedMap
comparator, values
-
Field Details
-
kv
The underlyingKVStore
. -
prefixMode
protected final boolean prefixModeWhether we are in "prefix" mode. -
reversed
protected final boolean reversedWhether the ordering of this instance is reversed. -
keyRange
Key range, or null for the entire range. -
keyFilter
Key filter, or null if all keys in the range should be visible.
-
-
Constructor Details
-
AbstractKVNavigableMap
Convenience constructor for when there are no range restrictions.- Parameters:
kv
- underlyingKVStore
prefixMode
- whether to allow keys to have trailing garbage- Throws:
IllegalArgumentException
- ifkv
is null
-
AbstractKVNavigableMap
Convenience constructor for when the range of visibleKVStore
keys is all keys sharing a givenbyte[]
prefix.- Parameters:
kv
- underlyingKVStore
prefixMode
- whether to allow keys to have trailing garbageprefix
- prefix defining minimum and maximum keys- Throws:
IllegalArgumentException
- ifkv
is nullIllegalArgumentException
- ifprefix
is null or empty
-
AbstractKVNavigableMap
Primary constructor.- Parameters:
kv
- underlyingKVStore
prefixMode
- whether to allow keys to have trailing garbagekeyRange
- key range restriction, or null for none- Throws:
IllegalArgumentException
- ifkv
is null
-
AbstractKVNavigableMap
protected AbstractKVNavigableMap(KVStore kv, boolean prefixMode, boolean reversed, KeyRange keyRange, KeyFilter keyFilter, Bounds<K> bounds) Internal constructor. Used for creating sub-maps and reversed views.Note: if
bounds
are set, thenkeyRange
must exclude all keys outside of those bounds.- Parameters:
kv
- underlyingKVStore
prefixMode
- whether to allow keys to have trailing garbagereversed
- whether ordering is reversed (impliesbounds
are also inverted, but notkeyRange
)keyRange
- key range restriction, or null for nonekeyFilter
- key filter, or null for nonebounds
- range restriction- Throws:
IllegalArgumentException
- ifkv
orbounds
is null
-
-
Method Details
-
get
-
entrySet
-
filterKeys
Create a view of this instance with additional filtering applied to the underlyingbyte[]
keys. Any map entry for which the corresponding key does not passkeyFilter
will be effectively hidden from view.The restrictions of the given
KeyFilter
will be added to any currentKeyFilter
restrictions on this instance. TheAbstractNavigableMap.bounds
associated with this instance will not change.- Parameters:
keyFilter
- additional key filtering to apply- Returns:
- filtered view of this instance
- Throws:
IllegalArgumentException
- ifkeyFilter
is null
-
isWithinLowerBound
Description copied from class:AbstractNavigableMap
Determine if the given element is within this instance's lower bound (if any).The implementation in
AbstractNavigableMap
returnsthis.bounds.isWithinLowerBound(this.comparator(), elem)
.- Overrides:
isWithinLowerBound
in classAbstractNavigableMap<K,
V> - Parameters:
key
- map key- Returns:
- true if
elem
is within this instance's lower bound, or this instance has no lower bound
-
isWithinUpperBound
Description copied from class:AbstractNavigableMap
Determine if the given element is within this instance's upper bound (if any).The implementation in
AbstractNavigableMap
returnsthis.bounds.isWithinUpperBound(this.comparator(), elem)
.- Overrides:
isWithinUpperBound
in classAbstractNavigableMap<K,
V> - Parameters:
key
- map key- Returns:
- true if
elem
is within this instance's upper bound, or this instance has no upper bound
-
createSubMap
Description copied from class:AbstractNavigableMap
Create a (possibly reversed) view of this instance with (possibly) tighter lower and/or upper bounds. ThenewBounds
are consistent with the new ordering (i.e., reversed relative to this instance's ordering ifreverse
is true) and have already been range-checked against this instance's current bounds.- Specified by:
createSubMap
in classAbstractNavigableMap<K,
V> - Parameters:
reverse
- whether the new map's ordering should be reversed relative to this instance's orderingnewBounds
- new bounds- Returns:
- restricted and/or reversed view of this instance
-
createSubMap
protected abstract NavigableMap<K,V> createSubMap(boolean newReversed, KeyRange newKeyRange, KeyFilter newKeyFilter, Bounds<K> newBounds) Create a (possibly reversed) view of this instance with (possibly) tighter lower and/or upper bounds and the givenKeyFilter
, if any. The bounds are consistent with the reversed ordering (i.e., reversed ifreverse
is true) and have already been range-checked against this instance's bounds.- Parameters:
newReversed
- whether the new map's ordering should be reversed (impliesnewBounds
are also inverted, but notkeyRange
); note: means "absolutely" reversed, not relative to this instancenewKeyRange
- new key range, or null for none; will be consistent withbounds
, if anynewKeyFilter
- new key filter, or null for nonenewBounds
- new bounds- Returns:
- restricted and/or filtered view of this instance
- Throws:
IllegalArgumentException
- ifnewBounds
is null
-
encodeKey
Encode the given key object into abyte[]
key. Note that this method must throwIllegalArgumentException
, notClassCastException
orNullPointerException
, ifobj
does not have the correct type or is an illegal null value.- Parameters:
writer
- output for encodedbyte[]
key corresponding toobj
obj
- map key object- Throws:
IllegalArgumentException
- ifobj
is not of the required Java type supported by this setIllegalArgumentException
- ifobj
is null and this set does not support null elements
-
decodeKey
Decode a key object from an encodedbyte[]
key.If not in prefix mode, all of
reader
must be consumed; otherwise, the consumed portion is the prefix and any following keys with the same prefix are ignored.- Parameters:
reader
- input for encoded bytes- Returns:
- decoded map key
-
decodeValue
Decode a value object from an encodedbyte[]
key/value pair.- Parameters:
pair
- key/value pair- Returns:
- decoded map value
-
isVisible
protected boolean isVisible(byte[] key) Determine if the givenbyte[]
key is visible in this map according to the configuredKeyRange
and/orKeyFilter
, if any.- Parameters:
key
- key to test- Returns:
- true if key is visible
- Throws:
IllegalArgumentException
- ifkey
is null- See Also:
-
encodeVisibleKey
Encode the given key object, if possible, and verify the correspondingbyte[]
key is visible, otherwise return null or throw an exception. Delegates toencodeKey(ByteWriter, Object)
to attempt the actual encoding.- Parameters:
obj
- key object to encode, possibly nullfail
- whether, ifobj
can't be encoded, to throw an exception (true) or return null (false)- Returns:
- encoed key for
obj
, or null iffail
is false andobj
has the wrong type or is out of bounds - Throws:
IllegalArgumentException
- iffail
is true andobj
has the wrong typeIllegalArgumentException
- iffail
is true and the resulting key is not visible
-