diff --git a/src/map.rs b/src/map.rs index 548ca0f9e..733b53424 100644 --- a/src/map.rs +++ b/src/map.rs @@ -619,6 +619,15 @@ impl HashMap { self.table.capacity() } + /// Returns the maximum number of elements the map could potentially hold + /// without reallocating. + /// + /// This number is an upper bound. + #[cfg_attr(feature = "inline-more", inline)] + pub fn max_capacity(&self) -> usize { + self.table.max_capacity() + } + /// An iterator visiting all keys in arbitrary order. /// The iterator element type is `&'a K`. /// diff --git a/src/raw/mod.rs b/src/raw/mod.rs index 1a6dced4b..22138c5ef 100644 --- a/src/raw/mod.rs +++ b/src/raw/mod.rs @@ -1389,6 +1389,15 @@ impl RawTable { self.table.items + self.table.growth_left } + /// Returns the maximum number of elements the map could potentially hold + /// without reallocating. + /// + /// This number is an upper bound. + #[inline] + pub fn max_capacity(&self) -> usize { + bucket_mask_to_capacity(self.table.bucket_mask) + } + /// Returns the number of elements in the table. #[inline] pub fn len(&self) -> usize { @@ -2485,6 +2494,15 @@ impl RawTableInner { // SAFETY: the caller must uphold the safety contract for `erase` method. self.set_ctrl(index, ctrl); self.items -= 1; + + // If the last item was removed we can do some cleanup + if unlikely(self.items == 0) { + let desired_capacity = bucket_mask_to_capacity(self.bucket_mask); + if self.growth_left <= desired_capacity / 2 { + // Restore an accurate view of the capacity + self.clear_no_drop() + } + } } }