By default, HashMap uses a hashing algorithm selected to provide
resistance against HashDoS attacks. The algorithm is randomly seeded, and a
reasonable best-effort is made to generate this seed from a high quality,
secure source of randomness provided by the host without blocking the
program. Because of this, the randomness of the seed depends on the output
quality of the system's random number generator when the seed is created.
In particular, seeds generated when the system's entropy pool is abnormally
low such as during system boot may be of a lower quality.

The default hashing algorithm is currently SipHash 1-3, though this is
subject to change at any point in the future. While its performance is very
competitive for medium sized keys, other hashing algorithms will outperform
it for small keys such as integers as well as large keys such as long
strings, though those algorithms will typically not protect against
attacks such as HashDoS.

It is required that the keys implement the Eq and Hash traits, although
this can frequently be achieved by using #[derive(PartialEq, Eq, Hash)].
If you implement these yourself, it is important that the following
property holds:

k1 == k2 -> hash(k1) == hash(k2)

In other words, if two keys are equal, their hashes must be equal.

It is a logic error for a key to be modified in such a way that the key's
hash, as determined by the Hash trait, or its equality, as determined by
the Eq trait, changes while it is in the map. This is normally only
possible through Cell, RefCell, global state, I/O, or unsafe code.

The hash table implementation is a Rust port of Google's SwissTable.
The original C++ version of SwissTable can be found here, and this
CppCon talk gives an overview of how the algorithm works.

HashMap also implements an Entry API, which allows
for more complex methods of getting, setting, updating and removing keys and
their values:

usestd::collections::HashMap;
// type inference lets us omit an explicit type signature (which// would be `HashMap<&str, u8>` in this example).letmutplayer_stats=HashMap::new();
fnrandom_stat_buff() ->u8 {
// could actually return some random value here - let's just return// some fixed value for now42
}
// insert a key only if it doesn't already existplayer_stats.entry("health").or_insert(100);
// insert a key using a function that provides a new value only if it// doesn't already existplayer_stats.entry("defence").or_insert_with(random_stat_buff);
// update a key, guarding against the key possibly not being setletstat=player_stats.entry("attack").or_insert(100);
*stat+=random_stat_buff();

Creates an empty HashMap which will use the given hash builder to hash
keys.

The created map has the default initial capacity.

Warning: hash_builder is normally randomly generated, and
is designed to allow HashMaps to be resistant to attacks that
cause many collisions and very poor performance. Setting it
manually using this function can expose a DoS attack vector.

Creates an empty HashMap with the specified capacity, using hash_builder
to hash the keys.

The hash map will be able to hold at least capacity elements without
reallocating. If capacity is 0, the hash map will not allocate.

Warning: hash_builder is normally randomly generated, and
is designed to allow HashMaps to be resistant to attacks that
cause many collisions and very poor performance. Setting it
manually using this function can expose a DoS attack vector.

Shrinks the capacity of the map with a lower limit. It will drop
down no lower than the supplied limit while maintaining the internal rules
and possibly leaving some space in accordance with the resize policy.

Panics if the current capacity is smaller than the supplied
minimum capacity.

If the map did have this key present, the value is updated, and the old
value is returned. The key is not updated, though; this matters for
types that can be == without being identical. See the module-level
documentation for more.

Raw entries provide the lowest level of control for searching and
manipulating a map. They must be manually initialized with a hash and
then manually searched. After this, insertions into a vacant entry
still require an owned key to be provided.

Raw entries are useful for such exotic situations as:

Hash memoization

Deferring the creation of an owned key until it is known to be required

Using a search key that doesn't work with the Borrow trait

Using custom comparison logic without newtype wrappers

Because raw entries provide much more low-level control, it's much easier
to put the HashMap into an inconsistent state which, while memory-safe,
will cause the map to produce seemingly random results. Higher-level and
more foolproof APIs like entry should be preferred when possible.

In particular, the hash used to initialized the raw entry must still be
consistent with the hash of the key that is ultimately stored in the entry.
This is because implementations of HashMap may need to recompute hashes
when resizing, at which point only the keys are available.

Raw entries give mutable access to the keys. This must not be used
to modify how the key would compare or hash, as the map will not re-evaluate
where the key should go, meaning the keys may become "lost" if their
location does not reflect their state. For instance, if you change a key
so that the map now contains keys which compare equal, search may start
acting erratically, with two keys randomly masking each other. Implementations
are free to assume this doesn't happen (within the limits of memory-safety).