From 2c5d2403d770e624bbb0b9ce8e970efa914a8602 Mon Sep 17 00:00:00 2001 From: arthurprs Date: Sat, 26 Nov 2016 17:30:29 +0100 Subject: [PATCH] Smarter HashMap/HashSet extend --- src/libstd/collections/hash/map.rs | 17 +++++++++++++---- src/libstd/collections/hash/set.rs | 10 +++------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index ece51d6d82616..9f9d0429fcadd 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1971,10 +1971,8 @@ impl FromIterator<(K, V)> for HashMap S: BuildHasher + Default { fn from_iter>(iter: T) -> HashMap { - let iterator = iter.into_iter(); - let lower = iterator.size_hint().0; - let mut map = HashMap::with_capacity_and_hasher(lower, Default::default()); - map.extend(iterator); + let mut map = HashMap::with_hasher(Default::default()); + map.extend(iter); map } } @@ -1985,6 +1983,17 @@ impl Extend<(K, V)> for HashMap S: BuildHasher { fn extend>(&mut self, iter: T) { + // Keys may be already present or show multiple times in the iterator. + // Reserve the entire hint lower bound if the map is empty. + // Otherwise reserve half the hint (rounded up), so the map + // will only resize twice in the worst case. + let iter = iter.into_iter(); + let reserve = if self.is_empty() { + iter.size_hint().0 + } else { + (iter.size_hint().0 + 1) / 2 + }; + self.reserve(reserve); for (k, v) in iter { self.insert(k, v); } diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 1ec7a4a7b639b..72af612f5696f 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -663,10 +663,8 @@ impl FromIterator for HashSet S: BuildHasher + Default { fn from_iter>(iter: I) -> HashSet { - let iterator = iter.into_iter(); - let lower = iterator.size_hint().0; - let mut set = HashSet::with_capacity_and_hasher(lower, Default::default()); - set.extend(iterator); + let mut set = HashSet::with_hasher(Default::default()); + set.extend(iter); set } } @@ -677,9 +675,7 @@ impl Extend for HashSet S: BuildHasher { fn extend>(&mut self, iter: I) { - for k in iter { - self.insert(k); - } + self.map.extend(iter.into_iter().map(|k| (k, ()))); } }