NavigableDictionary<TKey, TValue> Class
Definition
Represents a key-sorted dictionary augmented with order statistics - an IDictionary<TKey, TValue> that keeps its entries in key comparer order and answers nearest-neighbour ( TryGetFloorEntry(TKey, out KeyValuePair<TKey, TValue>) / TryGetCeilingEntry(TKey, out KeyValuePair<TKey, TValue>) / TryGetHigherEntry(TKey, out KeyValuePair<TKey, TValue>) / TryGetLowerEntry(TKey, out KeyValuePair<TKey, TValue>)), rank/select ( IndexOfKey(TKey) / GetAt(int)), and range-counting queries in O(log n).
public sealed class NavigableDictionary<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable where TKey : notnull
Type Parameters
TKeyThe type of keys in the dictionary. Keys must not be null.
TValueThe type of values in the dictionary. Values may be null.
- Inheritance
-
NavigableDictionary<TKey, TValue>
- Implements
-
IDictionary<TKey, TValue>ICollection<KeyValuePair<TKey, TValue>>IReadOnlyDictionary<TKey, TValue>IReadOnlyCollection<KeyValuePair<TKey, TValue>>IEnumerable<KeyValuePair<TKey, TValue>>
- Inherited Members
- Extension Methods
Examples
var quotes = new NavigableDictionary<decimal, string>();
quotes.Add(10.00m, "bid");
quotes.Add(10.25m, "mid");
quotes.Add(10.50m, "ask");
quotes.TryGetFloorEntry(10.30m, out var floor); // (10.25, "mid") - greatest key <= 10.30
quotes.TryGetCeilingKey(10.30m, out decimal ask); // 10.50 - least key >= 10.30
int rank = quotes.IndexOfKey(10.25m); // 1 - zero-based rank in key order
var median = quotes.GetAt(quotes.Count / 2); // (10.25, "mid") - entry with the k-th smallest key
int inBand = quotes.CountInRange(10.00m, 10.30m); // 2 - O(log n), no iteration
Remarks
NavigableDictionary<TKey, TValue> is backed by an order-statistic red-black tree: every node carries
the size of its subtree, maintained through all rotations, so positional queries read only size fields on a
root-to-node path. The node machinery is the key-value adaptation of the NavigableSet<T> core; see
Bodu.Collections/docs/navigable-collections-design.md for the backing-structure decision record.
Compared with SortedDictionary<TKey, TValue>, this type adds rank/select ( IndexOfKey(TKey) is the zero-based rank of a key; GetAt(int) is the entry with the k-th smallest key), O(log n) CountInRange(TKey, TKey), the four nearest-neighbour queries, and cheap Ascending() / Descending() / Range(TKey, TKey) views.
Keys are rejected when null, consistent with the rest of the Bodu collection family; values are unconstrained and may be null. Keys the comparer orders equal are the same key.
This type is not thread-safe.
Constructors
NavigableDictionary()
Initializes a new instance of the NavigableDictionary<TKey, TValue> class using the default comparer.
public NavigableDictionary()
NavigableDictionary(IComparer<TKey>?)
Initializes a new instance of the NavigableDictionary<TKey, TValue> class using the specified comparer.
public NavigableDictionary(IComparer<TKey>? comparer)
Parameters
NavigableDictionary(IEnumerable<KeyValuePair<TKey, TValue>>, IComparer<TKey>?)
Initializes a new instance of the NavigableDictionary<TKey, TValue> class containing the entries
from source, bulk-loaded into a balanced tree.
public NavigableDictionary(IEnumerable<KeyValuePair<TKey, TValue>> source, IComparer<TKey>? comparer = null)
Parameters
sourceIEnumerable<KeyValuePair<TKey, TValue>>The source entries. Must not be null.
comparerIComparer<TKey>The key ordering comparer, or null to use the default comparer.
Remarks
The source is sorted by key and built directly into a balanced tree - O(n log n) overall, O(n) after the sort. Comparer-equal duplicate keys are rejected, matching the Dictionary<TKey, TValue> collection-constructor contract.
Exceptions
- ArgumentNullException
sourceis null.- ArgumentException
sourcecontains a null key, or two entries whose keys the comparer orders equal.
Properties
Comparer
Gets the comparer that defines the key ordering.
public IComparer<TKey> Comparer { get; }
Property Value
- IComparer<TKey>
The active key ordering comparer.
Count
Gets the number of entries in the dictionary.
public int Count { get; }
Property Value
- int
The number of key/value pairs currently stored in the dictionary.
IsReadOnly
Gets a value indicating whether the dictionary is read-only.
public bool IsReadOnly { get; }
Property Value
this[TKey]
Gets or sets the value associated with the specified key.
public TValue this[TKey key] { get; set; }
Parameters
keyTKeyThe key of the value to get or set. Must not be null.
Property Value
- TValue
The value associated with
key.
Remarks
Assigning through the indexer upserts: a new key is inserted at its comparer position, and an existing key has its value overwritten in place. Overwriting a value is not a structural mutation and does not invalidate in-flight enumerators.
Exceptions
- ArgumentNullException
keyis null.- KeyNotFoundException
The property is read and the dictionary does not contain
key.
Keys
Gets a live view of the dictionary's keys in ascending comparer order.
public ICollection<TKey> Keys { get; }
Property Value
- ICollection<TKey>
A read-only collection over the current keys, smallest first.
Remarks
The view is live and cached per instance, so repeated reads of Keys do not allocate; enumeration follows ascending key order and is fail-fast against structural mutation.
MaxEntry
Gets the entry with the largest key in the dictionary.
public KeyValuePair<TKey, TValue> MaxEntry { get; }
Property Value
- KeyValuePair<TKey, TValue>
The maximum-key entry under the active comparer.
Exceptions
- InvalidOperationException
The dictionary is empty.
MinEntry
Gets the entry with the smallest key in the dictionary.
public KeyValuePair<TKey, TValue> MinEntry { get; }
Property Value
- KeyValuePair<TKey, TValue>
The minimum-key entry under the active comparer.
Exceptions
- InvalidOperationException
The dictionary is empty.
Values
Gets a live view of the dictionary's values in ascending key order.
public ICollection<TValue> Values { get; }
Property Value
- ICollection<TValue>
A read-only collection over the current values, ordered by their keys.
Remarks
The view is live and cached per instance, so repeated reads of Values do not allocate; enumeration follows ascending key order and is fail-fast against structural mutation.
Methods
Add(TKey, TValue)
Adds the specified key and value to the dictionary.
public void Add(TKey key, TValue value)
Parameters
keyTKeyThe key of the entry to add. Must not be null.
valueTValueThe value to associate with
key.
Remarks
This method follows the strict Add(TKey, TValue) contract and throws on a comparer-equal duplicate key. To insert or overwrite without throwing, assign through the indexer; to add only when absent without throwing, call TryAdd(TKey, TValue).
Exceptions
- ArgumentNullException
keyis null.- ArgumentException
The dictionary already contains a comparer-equal key.
Ascending()
Returns a live view of the entries in ascending key order.
public IEnumerable<KeyValuePair<TKey, TValue>> Ascending()
Returns
- IEnumerable<KeyValuePair<TKey, TValue>>
A lazily evaluated sequence over the current entries, smallest key first.
Remarks
The view is live: each fresh iteration re-resolves against the dictionary's current state, so mutations made after the view was obtained are reflected the next time it is iterated. Within a single iteration the view is fail-fast - any structural mutation causes the next advance to throw InvalidOperationException.
Clear()
Removes all entries from the dictionary.
public void Clear()
ContainsKey(TKey)
Determines whether the dictionary contains an entry with the specified key.
public bool ContainsKey(TKey key)
Parameters
keyTKeyThe key to locate. Must not be null.
Returns
Exceptions
- ArgumentNullException
keyis null.
ContainsValue(TValue)
Determines whether the dictionary contains an entry with the specified value.
public bool ContainsValue(TValue value)
Parameters
valueTValueThe value to locate, which may be null.
Returns
Remarks
This method performs a linear O(n) walk over the entries - values are not indexed. Use ContainsKey(TKey) for the O(log n) key lookup.
CopyTo(KeyValuePair<TKey, TValue>[], int)
Copies the entries to the specified array in ascending key order, starting at arrayIndex.
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
Parameters
arrayKeyValuePair<TKey, TValue>[]The destination array. Must not be null.
arrayIndexintThe destination start index.
Exceptions
- ArgumentNullException
arrayis null.- ArgumentOutOfRangeException
arrayIndexis negative.- ArgumentException
arraydoes not have enough space starting atarrayIndex.
CountInRange(TKey, TKey)
Returns the number of entries whose keys fall within the inclusive range [lowInclusive,
highInclusive].
public int CountInRange(TKey lowInclusive, TKey highInclusive)
Parameters
lowInclusiveTKeyThe inclusive lower key bound. Must not be null.
highInclusiveTKeyThe inclusive upper key bound. Must not be null.
Returns
- int
The count of stored entries whose keys are no smaller than the lower bound and no larger than the upper bound.
Remarks
Runs in O(log n) as a subtraction of two rank walks; neither bound needs to be present in the dictionary.
Exceptions
- ArgumentNullException
lowInclusiveorhighInclusiveis null.- ArgumentException
lowInclusiveorders afterhighInclusiveunder the active comparer.
Descending()
Returns a live view of the entries in descending key order.
public IEnumerable<KeyValuePair<TKey, TValue>> Descending()
Returns
- IEnumerable<KeyValuePair<TKey, TValue>>
A lazily evaluated sequence over the current entries, largest key first.
Remarks
The view is live: each fresh iteration re-resolves against the dictionary's current state, so mutations made after the view was obtained are reflected the next time it is iterated. Within a single iteration the view is fail-fast - any structural mutation causes the next advance to throw InvalidOperationException.
GetAt(int)
Returns the entry at the specified zero-based rank - the entry with the k-th smallest key.
public KeyValuePair<TKey, TValue> GetAt(int rank)
Parameters
rankintThe zero-based rank of the entry to select.
Returns
- KeyValuePair<TKey, TValue>
The entry whose key rank is
rank.
Remarks
Runs in O(log n) by descending on subtree sizes.
Exceptions
- ArgumentOutOfRangeException
rankis negative or greater than or equal to Count.
GetEnumerator()
Returns an enumerator that iterates through the dictionary in ascending key order.
public NavigableDictionary<TKey, TValue>.Enumerator GetEnumerator()
Returns
- NavigableDictionary<TKey, TValue>.Enumerator
An NavigableDictionary<TKey, TValue>.Enumerator over the dictionary entries.
IndexOfKey(TKey)
Returns the zero-based rank of key in ascending comparer order.
public int IndexOfKey(TKey key)
Parameters
keyTKeyThe key to locate. Must not be null.
Returns
- int
The number of stored keys smaller than
key, or-1if it is not present.
Remarks
Runs in O(log n) by accumulating subtree sizes along the search path.
Exceptions
- ArgumentNullException
keyis null.
Range(TKey, TKey)
Returns a live view of the entries whose keys fall within the inclusive range [ lowInclusive,
highInclusive] in ascending key order.
public IEnumerable<KeyValuePair<TKey, TValue>> Range(TKey lowInclusive, TKey highInclusive)
Parameters
lowInclusiveTKeyThe inclusive lower key bound. Must not be null.
highInclusiveTKeyThe inclusive upper key bound. Must not be null.
Returns
- IEnumerable<KeyValuePair<TKey, TValue>>
A lazily evaluated sequence over the in-range entries, smallest key first.
Remarks
The bounds need not be present in the dictionary. The walk descends directly to the first in-range entry and stops past the last, so iterating costs O(log n + k) for k yielded entries.
The view is live over the bound pair: each fresh iteration re-resolves against the dictionary's current state. Within a single iteration the view is fail-fast - any structural mutation causes the next advance to throw InvalidOperationException.
Exceptions
- ArgumentNullException
lowInclusiveorhighInclusiveis null.- ArgumentException
lowInclusiveorders afterhighInclusiveunder the active comparer.
Remove(TKey)
Removes the entry with the specified key from the dictionary.
public bool Remove(TKey key)
Parameters
keyTKeyThe key of the entry to remove. Must not be null.
Returns
Exceptions
- ArgumentNullException
keyis null.
Remove(TKey, out TValue)
Removes the entry with the specified key from the dictionary, returning the removed value.
public bool Remove(TKey key, out TValue value)
Parameters
keyTKeyThe key of the entry to remove. Must not be null.
valueTValueWhen this method returns true, the value that was associated with
key; otherwise, the default value ofTValue.
Returns
Exceptions
- ArgumentNullException
keyis null.
TryAdd(TKey, TValue)
Attempts to add the specified key and value to the dictionary.
public bool TryAdd(TKey key, TValue value)
Parameters
keyTKeyThe key of the entry to add. Must not be null.
valueTValueThe value to associate with
key.
Returns
- bool
true if the entry was added; otherwise, false when the dictionary already contains a comparer-equal key. The stored value is left unchanged on a rejected add.
Exceptions
- ArgumentNullException
keyis null.
TryGetCeilingEntry(TKey, out KeyValuePair<TKey, TValue>)
Attempts to get the entry with the least key greater than or equal to key.
public bool TryGetCeilingEntry(TKey key, out KeyValuePair<TKey, TValue> entry)
Parameters
keyTKeyThe reference key. Must not be null.
entryKeyValuePair<TKey, TValue>When this method returns true, the ceiling entry.
Returns
Exceptions
- ArgumentNullException
keyis null.
TryGetCeilingKey(TKey, out TKey)
Attempts to get the least key greater than or equal to key.
public bool TryGetCeilingKey(TKey key, out TKey ceilingKey)
Parameters
keyTKeyThe reference key. Must not be null.
ceilingKeyTKeyWhen this method returns true, the ceiling key.
Returns
Exceptions
- ArgumentNullException
keyis null.
TryGetFloorEntry(TKey, out KeyValuePair<TKey, TValue>)
Attempts to get the entry with the greatest key less than or equal to key.
public bool TryGetFloorEntry(TKey key, out KeyValuePair<TKey, TValue> entry)
Parameters
keyTKeyThe reference key. Must not be null.
entryKeyValuePair<TKey, TValue>When this method returns true, the floor entry.
Returns
Exceptions
- ArgumentNullException
keyis null.
TryGetFloorKey(TKey, out TKey)
Attempts to get the greatest key less than or equal to key.
public bool TryGetFloorKey(TKey key, out TKey floorKey)
Parameters
keyTKeyThe reference key. Must not be null.
floorKeyTKeyWhen this method returns true, the floor key.
Returns
Exceptions
- ArgumentNullException
keyis null.
TryGetHigherEntry(TKey, out KeyValuePair<TKey, TValue>)
Attempts to get the entry with the least key strictly greater than key.
public bool TryGetHigherEntry(TKey key, out KeyValuePair<TKey, TValue> entry)
Parameters
keyTKeyThe reference key. Must not be null.
entryKeyValuePair<TKey, TValue>When this method returns true, the next-higher entry.
Returns
Exceptions
- ArgumentNullException
keyis null.
TryGetHigherKey(TKey, out TKey)
Attempts to get the least key strictly greater than key.
public bool TryGetHigherKey(TKey key, out TKey higherKey)
Parameters
keyTKeyThe reference key. Must not be null.
higherKeyTKeyWhen this method returns true, the next-higher key.
Returns
Exceptions
- ArgumentNullException
keyis null.
TryGetLowerEntry(TKey, out KeyValuePair<TKey, TValue>)
Attempts to get the entry with the greatest key strictly less than key.
public bool TryGetLowerEntry(TKey key, out KeyValuePair<TKey, TValue> entry)
Parameters
keyTKeyThe reference key. Must not be null.
entryKeyValuePair<TKey, TValue>When this method returns true, the next-lower entry.
Returns
Exceptions
- ArgumentNullException
keyis null.
TryGetLowerKey(TKey, out TKey)
Attempts to get the greatest key strictly less than key.
public bool TryGetLowerKey(TKey key, out TKey lowerKey)
Parameters
keyTKeyThe reference key. Must not be null.
lowerKeyTKeyWhen this method returns true, the next-lower key.
Returns
Exceptions
- ArgumentNullException
keyis null.
TryGetMaxEntry(out KeyValuePair<TKey, TValue>)
Attempts to get the entry with the largest key in the dictionary.
public bool TryGetMaxEntry(out KeyValuePair<TKey, TValue> entry)
Parameters
entryKeyValuePair<TKey, TValue>When this method returns true, the maximum-key entry.
Returns
TryGetMinEntry(out KeyValuePair<TKey, TValue>)
Attempts to get the entry with the smallest key in the dictionary.
public bool TryGetMinEntry(out KeyValuePair<TKey, TValue> entry)
Parameters
entryKeyValuePair<TKey, TValue>When this method returns true, the minimum-key entry.
Returns
TryGetValue(TKey, out TValue)
Attempts to retrieve the value associated with the specified key.
public bool TryGetValue(TKey key, out TValue value)
Parameters
keyTKeyThe key of the value to retrieve. Must not be null.
valueTValueWhen this method returns true, the value associated with
key; otherwise, the default value ofTValue.
Returns
Exceptions
- ArgumentNullException
keyis null.
Explicit Interface Implementations
ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue>)
Adds item via the Add(T) contract.
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
Parameters
itemKeyValuePair<TKey, TValue>The key/value pair to add.
Exceptions
- ArgumentNullException
item.Keyis null.- ArgumentException
The dictionary already contains a comparer-equal key.
ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue>)
Determines whether the dictionary contains an entry matching both the key and the value of
item.
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
Parameters
itemKeyValuePair<TKey, TValue>The key/value pair to locate.
Returns
- bool
true if an entry with a comparer-equal key exists whose value equals
item.Valueunder Default; otherwise, false.
Exceptions
- ArgumentNullException
item.Keyis null.
ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue>)
Removes the entry matching both the key and the value of item.
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
Parameters
itemKeyValuePair<TKey, TValue>The key/value pair to remove.
Returns
Exceptions
- ArgumentNullException
item.Keyis null.
IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
Returns an enumerator that iterates through the collection.
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
Returns
- IEnumerator<KeyValuePair<TKey, TValue>>
An enumerator that can be used to iterate through the collection.
IReadOnlyDictionary<TKey, TValue>.Keys
Gets an enumerable collection that contains the keys in the read-only dictionary.
IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys { get; }
Returns
- IEnumerable<TKey>
An enumerable collection that contains the keys in the read-only dictionary.
IReadOnlyDictionary<TKey, TValue>.Values
Gets an enumerable collection that contains the values in the read-only dictionary.
IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values { get; }
Returns
- IEnumerable<TValue>
An enumerable collection that contains the values in the read-only dictionary.
IEnumerable.GetEnumerator()
Returns an enumerator that iterates through a collection.
IEnumerator IEnumerable.GetEnumerator()
Returns
- IEnumerator
An IEnumerator object that can be used to iterate through the collection.
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |