pub struct HashMap<K, V, H = RandomState>where
H: BuildHasher,{ /* private fields */ }
Expand description
Scalable concurrent hash map.
HashMap
is a concurrent hash map data structure optimized for highly concurrent workloads.
HashMap
has a dynamically sized array of buckets where a bucket is a fixed-size hash table
with linear probing that can be expanded by allocating a linked list of smaller buckets when it
is full.
§The key features of HashMap
- Non-sharded: data is stored in a single array of entry buckets.
- Non-blocking resizing: resizing does not block other threads or tasks.
- Automatic resizing: grows or shrinks as needed.
- Incremental resizing: entries in the old bucket array are incrementally relocated.
- No busy waiting: no spin locks or hot loops to wait for desired resources.
- Linearizability:
HashMap
manipulation methods are linearizable.
§The key statistics for HashMap
- The expected size of metadata for a single entry: 2 bytes.
- The expected number of atomic write operations required for an operation on a single key: 2.
- The expected number of atomic variables accessed during a single key operation: 2.
- The number of entries managed by a single bucket without a linked list: 32.
- The expected maximum linked list length when a resize is triggered: log(capacity) / 8.
§Locking behavior
§Bucket access
Bucket arrays are protected by sdd
, thus allowing lock-free access to them.
§Entry access
Each read/write access to an entry is serialized by the read-write lock in the bucket containing
the entry. There are no container-level locks, therefore, the larger the HashMap
gets, the
lower the chance that the bucket-level lock will be contended.
§Resize
Resizing of the HashMap
is non-blocking and lock-free; resizing does not block any other
read/write access to the HashMap
or resizing attempts. Resizing is analogous to pushing a
new bucket array into a lock-free stack. Each entry in the old bucket array will be
incrementally relocated to the new bucket array upon future access to the HashMap
, and the old
bucket array is dropped when it becomes empty and unreachable.
§Synchronous methods in an asynchronous code block
It is generally not recommended to use blocking methods, such as HashMap::insert_sync
, in an
asynchronous code block or poll
, since it may lead to deadlocks
or performance degradation.
§Unwind safety
HashMap
is impervious to out-of-memory errors and panics in user-specified code under one
condition: H::Hasher::hash
, K::drop
and V::drop
must not panic.
Implementations§
Source§impl<K, V, H> HashMap<K, V, H>where
H: BuildHasher,
impl<K, V, H> HashMap<K, V, H>where
H: BuildHasher,
Sourcepub const fn with_hasher(build_hasher: H) -> Self
pub const fn with_hasher(build_hasher: H) -> Self
Creates an empty HashMap
with the given BuildHasher
.
§Examples
use scc::HashMap;
use std::collections::hash_map::RandomState;
let hashmap: HashMap<u64, u32, RandomState> = HashMap::with_hasher(RandomState::new());
Sourcepub fn with_capacity_and_hasher(capacity: usize, build_hasher: H) -> Self
pub fn with_capacity_and_hasher(capacity: usize, build_hasher: H) -> Self
Creates an empty HashMap
with the specified capacity and BuildHasher
.
The actual capacity is equal to or greater than the specified capacity.
§Examples
use scc::HashMap;
use std::collections::hash_map::RandomState;
let hashmap: HashMap<u64, u32, RandomState> =
HashMap::with_capacity_and_hasher(1000, RandomState::new());
let result = hashmap.capacity();
assert_eq!(result, 1024);
Source§impl<K, V, H> HashMap<K, V, H>
impl<K, V, H> HashMap<K, V, H>
Sourcepub fn reserve(
&self,
additional_capacity: usize,
) -> Option<Reserve<'_, K, V, H>>
pub fn reserve( &self, additional_capacity: usize, ) -> Option<Reserve<'_, K, V, H>>
Temporarily increases the minimum capacity of the HashMap
to prevent shrinking.
A Reserve
is returned if the HashMap
can increase the minimum capacity. The
increased capacity is not exclusively owned by the returned Reserve
, allowing others to
benefit from it. The memory for the additional space may not be immediately allocated if
the HashMap
is empty or currently being resized; however, once the memory is eventually reserved,
the capacity will not shrink below the additional capacity until the returned
Reserve
is dropped.
§Errors
Returns None
if a too large number is given.
§Examples
use scc::HashMap;
let hashmap: HashMap<usize, usize> = HashMap::with_capacity(1000);
assert_eq!(hashmap.capacity(), 1024);
let reserved = hashmap.reserve(10000);
assert!(reserved.is_some());
assert_eq!(hashmap.capacity(), 16384);
assert!(hashmap.reserve(usize::MAX).is_none());
assert_eq!(hashmap.capacity(), 16384);
for i in 0..16 {
assert!(hashmap.insert_sync(i, i).is_ok());
}
drop(reserved);
assert_eq!(hashmap.capacity(), 1024);
Sourcepub async fn entry_async(&self, key: K) -> Entry<'_, K, V, H>
pub async fn entry_async(&self, key: K) -> Entry<'_, K, V, H>
Gets the entry associated with the given key in the map for in-place manipulation.
§Examples
use scc::HashMap;
let hashmap: HashMap<char, u32> = HashMap::default();
let future_entry = hashmap.entry_async('b');
Sourcepub fn entry_sync(&self, key: K) -> Entry<'_, K, V, H>
pub fn entry_sync(&self, key: K) -> Entry<'_, K, V, H>
Gets the entry associated with the given key in the map for in-place manipulation.
§Examples
use scc::HashMap;
let hashmap: HashMap<char, u32> = HashMap::default();
for ch in "a short treatise on fungi".chars() {
hashmap.entry_sync(ch).and_modify(|counter| *counter += 1).or_insert(1);
}
assert_eq!(hashmap.read_sync(&'s', |_, v| *v), Some(2));
assert_eq!(hashmap.read_sync(&'t', |_, v| *v), Some(3));
assert!(hashmap.read_sync(&'y', |_, v| *v).is_none());
Sourcepub fn try_entry(&self, key: K) -> Option<Entry<'_, K, V, H>>
pub fn try_entry(&self, key: K) -> Option<Entry<'_, K, V, H>>
Tries to get the entry associated with the given key in the map for in-place manipulation.
Returns None
if the entry could not be locked.
§Examples
use scc::HashMap;
let hashmap: HashMap<usize, usize> = HashMap::default();
assert!(hashmap.insert_sync(0, 1).is_ok());
assert!(hashmap.try_entry(0).is_some());
Sourcepub async fn begin_async(&self) -> Option<OccupiedEntry<'_, K, V, H>>
pub async fn begin_async(&self) -> Option<OccupiedEntry<'_, K, V, H>>
Begins iterating over entries by getting the first occupied entry.
The returned OccupiedEntry
in combination with OccupiedEntry::next_async
can act as
a mutable iterator over entries.
§Examples
use scc::HashMap;
let hashmap: HashMap<char, u32> = HashMap::default();
let future_entry = hashmap.begin_async();
Sourcepub fn begin_sync(&self) -> Option<OccupiedEntry<'_, K, V, H>>
pub fn begin_sync(&self) -> Option<OccupiedEntry<'_, K, V, H>>
Begins iterating over entries by getting the first occupied entry.
The returned OccupiedEntry
in combination with OccupiedEntry::next_sync
can act as a
mutable iterator over entries.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
let mut first_entry = hashmap.begin_sync().unwrap();
*first_entry.get_mut() = 2;
assert!(first_entry.next_sync().is_none());
assert_eq!(hashmap.read_sync(&1, |_, v| *v), Some(2));
Sourcepub async fn any_async<P: FnMut(&K, &V) -> bool>(
&self,
pred: P,
) -> Option<OccupiedEntry<'_, K, V, H>>
pub async fn any_async<P: FnMut(&K, &V) -> bool>( &self, pred: P, ) -> Option<OccupiedEntry<'_, K, V, H>>
Finds any entry satisfying the supplied predicate for in-place manipulation.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_entry = hashmap.any_async(|k, _| *k == 2);
Sourcepub fn any_sync<P: FnMut(&K, &V) -> bool>(
&self,
pred: P,
) -> Option<OccupiedEntry<'_, K, V, H>>
pub fn any_sync<P: FnMut(&K, &V) -> bool>( &self, pred: P, ) -> Option<OccupiedEntry<'_, K, V, H>>
Finds any entry satisfying the supplied predicate for in-place manipulation.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
assert!(hashmap.insert_sync(2, 3).is_ok());
let mut entry = hashmap.any_sync(|k, _| *k == 2).unwrap();
assert_eq!(*entry.get(), 3);
Sourcepub async fn insert_async(&self, key: K, val: V) -> Result<(), (K, V)>
pub async fn insert_async(&self, key: K, val: V) -> Result<(), (K, V)>
Inserts a key-value pair into the HashMap
.
§Note
If the key exists, the value is not updated. upsert_async
provides a way to update the value if the key exists.
§Errors
Returns an error containing the supplied key-value pair if the key exists.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
Sourcepub fn insert_sync(&self, key: K, val: V) -> Result<(), (K, V)>
pub fn insert_sync(&self, key: K, val: V) -> Result<(), (K, V)>
Inserts a key-value pair into the HashMap
.
§Note
If the key exists, the value is not updated. upsert_sync
provides a way to update the value if the key exists.
§Errors
Returns an error containing the supplied key-value pair if the key exists.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
assert_eq!(hashmap.insert_sync(1, 1).unwrap_err(), (1, 1));
Sourcepub async fn upsert_async(&self, key: K, val: V) -> Option<V>
pub async fn upsert_async(&self, key: K, val: V) -> Option<V>
Sourcepub fn upsert_sync(&self, key: K, val: V) -> Option<V>
pub fn upsert_sync(&self, key: K, val: V) -> Option<V>
Upserts a key-value pair into the HashMap
.
Returns the old value if the HashMap
has this key present, or returns None
.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.upsert_sync(1, 0).is_none());
assert_eq!(hashmap.upsert_sync(1, 1).unwrap(), 0);
assert_eq!(hashmap.read_sync(&1, |_, v| *v).unwrap(), 1);
Sourcepub async fn update_async<Q, U, R>(&self, key: &Q, updater: U) -> Option<R>
pub async fn update_async<Q, U, R>(&self, key: &Q, updater: U) -> Option<R>
Updates an existing key-value pair in-place.
Returns None
if the key does not exist.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
let future_update = hashmap.update_async(&1, |_, v| { *v = 2; *v });
Sourcepub fn update_sync<Q, U, R>(&self, key: &Q, updater: U) -> Option<R>
pub fn update_sync<Q, U, R>(&self, key: &Q, updater: U) -> Option<R>
Updates an existing key-value pair in-place.
Returns None
if the key does not exist.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.update_sync(&1, |_, _| true).is_none());
assert!(hashmap.insert_sync(1, 0).is_ok());
assert_eq!(hashmap.update_sync(&1, |_, v| { *v = 2; *v }).unwrap(), 2);
assert_eq!(hashmap.read_sync(&1, |_, v| *v).unwrap(), 2);
Sourcepub async fn remove_async<Q>(&self, key: &Q) -> Option<(K, V)>
pub async fn remove_async<Q>(&self, key: &Q) -> Option<(K, V)>
Removes a key-value pair if the key exists.
Returns None
if the key does not exist.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
let future_remove = hashmap.remove_async(&11);
Sourcepub fn remove_sync<Q>(&self, key: &Q) -> Option<(K, V)>
pub fn remove_sync<Q>(&self, key: &Q) -> Option<(K, V)>
Removes a key-value pair if the key exists.
Returns None
if the key does not exist.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.remove_sync(&1).is_none());
assert!(hashmap.insert_sync(1, 0).is_ok());
assert_eq!(hashmap.remove_sync(&1).unwrap(), (1, 0));
Sourcepub async fn remove_if_async<Q, F: FnOnce(&mut V) -> bool>(
&self,
key: &Q,
condition: F,
) -> Option<(K, V)>
pub async fn remove_if_async<Q, F: FnOnce(&mut V) -> bool>( &self, key: &Q, condition: F, ) -> Option<(K, V)>
Removes a key-value pair if the key exists and the given condition is met.
Returns None
if the key does not exist or the condition was not met.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
let future_remove = hashmap.remove_if_async(&11, |_| true);
Sourcepub fn remove_if_sync<Q, F: FnOnce(&mut V) -> bool>(
&self,
key: &Q,
condition: F,
) -> Option<(K, V)>
pub fn remove_if_sync<Q, F: FnOnce(&mut V) -> bool>( &self, key: &Q, condition: F, ) -> Option<(K, V)>
Removes a key-value pair if the key exists and the given condition is met.
Returns None
if the key does not exist or the condition was not met.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
assert!(hashmap.remove_if_sync(&1, |v| { *v += 1; false }).is_none());
assert_eq!(hashmap.remove_if_sync(&1, |v| *v == 1).unwrap(), (1, 1));
Sourcepub async fn get_async<Q>(&self, key: &Q) -> Option<OccupiedEntry<'_, K, V, H>>
pub async fn get_async<Q>(&self, key: &Q) -> Option<OccupiedEntry<'_, K, V, H>>
Gets an OccupiedEntry
corresponding to the key for in-place modification.
OccupiedEntry
exclusively owns the entry, preventing others from gaining access to it:
use read_async
if read-only access is sufficient.
Returns None
if the key does not exist.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
let future_get = hashmap.get_async(&11);
Sourcepub fn get_sync<Q>(&self, key: &Q) -> Option<OccupiedEntry<'_, K, V, H>>
pub fn get_sync<Q>(&self, key: &Q) -> Option<OccupiedEntry<'_, K, V, H>>
Gets an OccupiedEntry
corresponding to the key for in-place modification.
OccupiedEntry
exclusively owns the entry, preventing others from gaining access to it:
use read_sync
if read-only access is sufficient.
Returns None
if the key does not exist.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.get_sync(&1).is_none());
assert!(hashmap.insert_sync(1, 10).is_ok());
assert_eq!(*hashmap.get_sync(&1).unwrap().get(), 10);
*hashmap.get_sync(&1).unwrap() = 11;
assert_eq!(*hashmap.get_sync(&1).unwrap(), 11);
Sourcepub async fn read_async<Q, R, F: FnOnce(&K, &V) -> R>(
&self,
key: &Q,
reader: F,
) -> Option<R>
pub async fn read_async<Q, R, F: FnOnce(&K, &V) -> R>( &self, key: &Q, reader: F, ) -> Option<R>
Reads a key-value pair.
Returns None
if the key does not exist.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(11, 17);
let future_read = hashmap.read_async(&11, |_, v| *v);
Sourcepub fn read_sync<Q, R, F: FnOnce(&K, &V) -> R>(
&self,
key: &Q,
reader: F,
) -> Option<R>
pub fn read_sync<Q, R, F: FnOnce(&K, &V) -> R>( &self, key: &Q, reader: F, ) -> Option<R>
Reads a key-value pair.
Returns None
if the key does not exist.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.read_sync(&1, |_, v| *v).is_none());
assert!(hashmap.insert_sync(1, 10).is_ok());
assert_eq!(hashmap.read_sync(&1, |_, v| *v).unwrap(), 10);
Sourcepub async fn contains_async<Q>(&self, key: &Q) -> bool
pub async fn contains_async<Q>(&self, key: &Q) -> bool
Sourcepub fn contains_sync<Q>(&self, key: &Q) -> bool
pub fn contains_sync<Q>(&self, key: &Q) -> bool
Sourcepub async fn iter_async<F: FnMut(&K, &V) -> bool>(&self, f: F) -> bool
pub async fn iter_async<F: FnMut(&K, &V) -> bool>(&self, f: F) -> bool
Iterates over entries asynchronously for reading.
Stops iterating when the closure returns false
, and this method also returns false
.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u64> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
async {
let result = hashmap.iter_async(|k, v| {
false
}).await;
assert!(!result);
};
Sourcepub fn iter_sync<F: FnMut(&K, &V) -> bool>(&self, f: F) -> bool
pub fn iter_sync<F: FnMut(&K, &V) -> bool>(&self, f: F) -> bool
Iterates over entries synchronously for reading.
Stops iterating when the closure returns false
, and this method also returns false
.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u64> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
assert!(hashmap.insert_sync(2, 1).is_ok());
let mut acc = 0_u64;
let result = hashmap.iter_sync(|k, v| {
acc += *k;
acc += *v;
true
});
assert!(result);
assert_eq!(acc, 4);
Sourcepub async fn iter_mut_async<F: FnMut(ConsumableEntry<'_, '_, K, V>) -> bool>(
&self,
f: F,
) -> bool
pub async fn iter_mut_async<F: FnMut(ConsumableEntry<'_, '_, K, V>) -> bool>( &self, f: F, ) -> bool
Iterates over entries asynchronously for modification.
Stops iterating when the closure returns false
, and this method also returns false
.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
assert!(hashmap.insert_sync(2, 1).is_ok());
async {
let result = hashmap.iter_mut_async(|entry| {
if entry.0 == 1 {
entry.consume();
return false;
}
true
}).await;
assert!(!result);
assert_eq!(hashmap.len(), 1);
};
Sourcepub fn iter_mut_sync<F: FnMut(ConsumableEntry<'_, '_, K, V>) -> bool>(
&self,
f: F,
) -> bool
pub fn iter_mut_sync<F: FnMut(ConsumableEntry<'_, '_, K, V>) -> bool>( &self, f: F, ) -> bool
Iterates over entries synchronously for modification.
Stops iterating when the closure returns false
, and this method also returns false
.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
assert!(hashmap.insert_sync(2, 1).is_ok());
assert!(hashmap.insert_sync(3, 2).is_ok());
let result = hashmap.iter_mut_sync(|entry| {
if entry.0 == 1 {
entry.consume();
return false;
}
true
});
assert!(!result);
assert!(!hashmap.contains_sync(&1));
assert_eq!(hashmap.len(), 2);
Sourcepub async fn retain_async<F: FnMut(&K, &mut V) -> bool>(&self, pred: F)
pub async fn retain_async<F: FnMut(&K, &mut V) -> bool>(&self, pred: F)
Retains the entries specified by the predicate.
This method allows the predicate closure to modify the value field.
Entries that have existed since the invocation of the method are guaranteed to be visited
if they are not removed, however the same entry can be visited more than once if the
HashMap
gets resized by another thread.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
let future_insert = hashmap.insert_async(1, 0);
let future_retain = hashmap.retain_async(|k, v| *k == 1);
Sourcepub fn retain_sync<F: FnMut(&K, &mut V) -> bool>(&self, pred: F)
pub fn retain_sync<F: FnMut(&K, &mut V) -> bool>(&self, pred: F)
Retains the entries specified by the predicate.
This method allows the predicate closure to modify the value field.
Entries that have existed since the invocation of the method are guaranteed to be visited
if they are not removed, however the same entry can be visited more than once if the
HashMap
gets resized by another thread.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
assert!(hashmap.insert_sync(2, 1).is_ok());
assert!(hashmap.insert_sync(3, 2).is_ok());
hashmap.retain_sync(|k, v| *k == 1 && *v == 0);
assert!(hashmap.contains_sync(&1));
assert!(!hashmap.contains_sync(&2));
assert!(!hashmap.contains_sync(&3));
Sourcepub async fn clear_async(&self)
pub async fn clear_async(&self)
Sourcepub fn clear_sync(&self)
pub fn clear_sync(&self)
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of entries in the HashMap
.
It reads the entire metadata area of the bucket array to calculate the number of valid
entries, making its time complexity O(N)
. Furthermore, it may overcount entries if an old
bucket array has not yet been dropped.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert!(hashmap.insert_sync(1, 0).is_ok());
assert_eq!(hashmap.len(), 1);
Sourcepub fn capacity(&self) -> usize
pub fn capacity(&self) -> usize
Returns the capacity of the HashMap
.
§Examples
use scc::HashMap;
let hashmap_default: HashMap<u64, u32> = HashMap::default();
assert_eq!(hashmap_default.capacity(), 0);
assert!(hashmap_default.insert_sync(1, 0).is_ok());
assert_eq!(hashmap_default.capacity(), 64);
let hashmap: HashMap<u64, u32> = HashMap::with_capacity(1000);
assert_eq!(hashmap.capacity(), 1024);
Sourcepub fn capacity_range(&self) -> RangeInclusive<usize>
pub fn capacity_range(&self) -> RangeInclusive<usize>
Returns the current capacity range of the HashMap
.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::default();
assert_eq!(hashmap.capacity_range(), 0..=(1_usize << (usize::BITS - 1)));
let reserved = hashmap.reserve(1000);
assert_eq!(hashmap.capacity_range(), 1000..=(1_usize << (usize::BITS - 1)));
Sourcepub fn bucket_index<Q>(&self, key: &Q) -> usize
pub fn bucket_index<Q>(&self, key: &Q) -> usize
Returns the index of the bucket that may contain the key.
The method returns the index of the bucket associated with the key. The number of buckets
can be calculated by dividing the capacity by 32
.
§Examples
use scc::HashMap;
let hashmap: HashMap<u64, u32> = HashMap::with_capacity(1024);
let bucket_index = hashmap.bucket_index(&11);
assert!(bucket_index < hashmap.capacity() / 32);
Source§impl<K, V> HashMap<K, V, RandomState>
impl<K, V> HashMap<K, V, RandomState>
Sourcepub fn with_capacity(capacity: usize) -> Self
pub fn with_capacity(capacity: usize) -> Self
Trait Implementations§
Source§impl<K, V, H> Debug for HashMap<K, V, H>
impl<K, V, H> Debug for HashMap<K, V, H>
Source§fn fmt(&self, f: &mut Formatter<'_>) -> Result
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Iterates over all the entries in the HashMap
to print them.
§Locking behavior
Shared locks on buckets are acquired during iteration, therefore any Entry
,
OccupiedEntry
, or VacantEntry
owned by the current thread will lead to deadlocks.