Smarter HashMap/HashSet extend

This commit is contained in:
arthurprs 2016-11-26 17:30:29 +01:00
parent 73e98a0210
commit 2c5d2403d7
2 changed files with 16 additions and 11 deletions

View File

@ -1971,10 +1971,8 @@ impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
S: BuildHasher + Default
{
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> HashMap<K, V, S> {
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<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
S: BuildHasher
{
fn extend<T: IntoIterator<Item = (K, V)>>(&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);
}

View File

@ -663,10 +663,8 @@ impl<T, S> FromIterator<T> for HashSet<T, S>
S: BuildHasher + Default
{
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> HashSet<T, S> {
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<T, S> Extend<T> for HashSet<T, S>
S: BuildHasher
{
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
for k in iter {
self.insert(k);
}
self.map.extend(iter.into_iter().map(|k| (k, ())));
}
}