Awesome hash table implementation in just Rust (stable, no unsafe code).
Please read the API documentation here
__
__ https://docs.rs/indexmap/
|buildstatus| |crates|_
.. |crates| image:: https://img.shields.io/crates/v/indexmap.svg .. _crates: https://crates.io/crates/indexmap
.. |buildstatus| image:: https://travis-ci.org/bluss/indexmap.svg .. _buildstatus: https://travis-ci.org/bluss/indexmap
This crate was originally released under the name ordermap
, but it was
renamed (with no change in functionality) to indexmap
to better emphasize
its features.
This was inspired by Python 3.6's new dict implementation (which remembers the insertion order and is fast to iterate, and is compact in memory).
Some of those features were translated to Rust, and some were not. The result was indexmap, a hash table that has following properties:
.remove()
.Uses robin hood hashing just like Rust's libstd HashMap
.
.reserve()
exists but does not have a complete implementationIndexMap
derives a couple of performance facts directly from how it is constructed,
which is roughly:
Two vectors, the first, sparse, with hashes and key-value indices, and the second, dense, the key-value pairs.
Lookup is fast-ish because the hashes and indices are densely stored. Lookup also is slow-ish since hashes and key-value pairs are stored in separate places. (Visible when cpu caches size is limiting.)
In practice, IndexMap
has been tested out as the hashmap in rustc in PR45282_ and
the performance was roughly on par across the whole workload.
IndexMap
, or its strongest performance points
fits your workload, it might be the best hash table implementation... _PR45282: https://github.com/rust-lang/rust/pull/45282
.swap_remove()
perturbs the order, like the method name says)..pop() -> Option<(K, V)>
in O(1) time.IndexMap::new()
is empty and uses no allocation until you insert something.unsafe
.IndexMut
.It can be an indexable ordered map in the current fashion (This was implemented in 0.2.0, for potential use as a graph datastructure).
Idea for more cache efficient lookup (This was implemented in 0.1.2).
Current indices: Vec<Pos>
. Pos
is interpreted as (u32, u32)
more
or less when .raw_capacity()
fits in 32 bits. Pos
then stores both the lower
half of the hash and the entry index.
This means that the hash values in Bucket
don't need to be accessed
while scanning for an entry.
1.0.0
indexmap
! (the crate and datastructure
formerly known as “ordermap”)OccupiedEntry::insert
changed its signature, to use &mut self
for
the method receiver, matching the equivalent method for a standard
HashMap
. Thanks to @dtolnay for finding this bug.OrderMap
,
OrderSet
, ordermap!{}
, orderset!{}
. Use the new IndexMap
etc names instead.0.4.1
indexmap
; the ordermap
crate is now deprecated
and the types OrderMap/Set
now have a deprecation notice.0.4.0
ordermap
under that name,
because the crate is going to be renamed to indexmap
(with types
IndexMap
, IndexSet
) and no change in functionality!The map and its associated structs moved into the map
submodule of the
crate, so that the map and set are symmetric
The iterators, Entry
and other structs are now under ordermap::map::
Internally refactored OrderMap<K, V, S>
so that all the main algorithms
(insertion, lookup, removal etc) that don't use the S
parameter (the
hasher) are compiled without depending on S
, which reduces generics bloat.
Entry<K, V>
no longer has a type parameter S
, which is just like
the standard HashMap
's entry.
Minimum Rust version requirement increased to Rust 1.18
0.3.5
0.3.4
.retain()
methods for OrderMap
and OrderSet
now
traverse the elements in order, and the retained elements keep their order.sort_by()
, .sort_keys()
to OrderMap
and
.sort_by()
, .sort()
to OrderSet
. These methods allow you to
sort the maps in place efficiently.0.3.3
0.3.2
OrderSet
by @cuviper!OrderMap::drain
is now (too) a double ended iterator.0.3.1
collect
method to the underlying
iterator as well.0.3.0
get_pair
, get_pair_index
were both replaced by
get_full
(and the same for the mutable case).swap_remove_pair
replaced by swap_remove_full
.MutableKeys
for opt-in mutable key access. Mutable key access
is only possible through the methods of this extension trait.Equivalent
for key equivalence. This extends the
Borrow
trait mechanism for OrderMap::get
in a backwards compatible
way, just some minor type inference related issues may become apparent.
See #10
__ for more information.Extend<(&K, &V)>
by @xfix.__ https://github.com/bluss/ordermap/pull/10
0.2.13
.index()
on the entry types by @garro95.0.2.12
.with_hasher()
, .hasher()
.0.2.11
ExactSizeIterator
for the iterators. By @Binero.Box<[Pos]>
internally, saving a word in the OrderMap
struct."serde-1"
. By @xfix.0.2.10
.drain(..)
by @stevej.0.2.9
.is_empty()
by @overvenus.PartialEq, Eq
by @overvenus..sorted_by()
.0.2.8
.values()
and .values_mut()
.0.2.7
.retain()
.0.2.6
OccupiedEntry::remove_entry
and other minor entry methods,
so that it now has all the features of HashMap
's entries.0.2.5
.pop()
slightly.0.2.4
.insert()
(#3
__) by @pczarn.__ https://github.com/bluss/ordermap/pull/3
0.2.3
Entry
for now, so that it works on hashmaps with non-default
hasher. However, there's a lingering compat issue since libstd HashMap
does not parameterize its entries by the hasher (S
typarm)..nth()
.0.2.2
Debug
impl by default.0.2.1
0.2.0
HashMap
methods & compat with its API..entry()
(the simplest parts of the API)..reserve()
(placeholder impl)..remove()
as synonym for .swap_remove()
..insert()
to swap value if the entry already exists, and
return Option
..get_index()
, .get_index_mut()
, .swap_remove_index()
,
.get_pair_index()
, .get_pair_index_mut()
.0.1.2
Pos
which improves cache utilization
and lookup performance.0.1.1