Skip to content

Commit 2c5d240

Browse files
committed
Smarter HashMap/HashSet extend
1 parent 73e98a0 commit 2c5d240

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

src/libstd/collections/hash/map.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -1971,10 +1971,8 @@ impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
19711971
S: BuildHasher + Default
19721972
{
19731973
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> HashMap<K, V, S> {
1974-
let iterator = iter.into_iter();
1975-
let lower = iterator.size_hint().0;
1976-
let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
1977-
map.extend(iterator);
1974+
let mut map = HashMap::with_hasher(Default::default());
1975+
map.extend(iter);
19781976
map
19791977
}
19801978
}
@@ -1985,6 +1983,17 @@ impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
19851983
S: BuildHasher
19861984
{
19871985
fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
1986+
// Keys may be already present or show multiple times in the iterator.
1987+
// Reserve the entire hint lower bound if the map is empty.
1988+
// Otherwise reserve half the hint (rounded up), so the map
1989+
// will only resize twice in the worst case.
1990+
let iter = iter.into_iter();
1991+
let reserve = if self.is_empty() {
1992+
iter.size_hint().0
1993+
} else {
1994+
(iter.size_hint().0 + 1) / 2
1995+
};
1996+
self.reserve(reserve);
19881997
for (k, v) in iter {
19891998
self.insert(k, v);
19901999
}

src/libstd/collections/hash/set.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -663,10 +663,8 @@ impl<T, S> FromIterator<T> for HashSet<T, S>
663663
S: BuildHasher + Default
664664
{
665665
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> HashSet<T, S> {
666-
let iterator = iter.into_iter();
667-
let lower = iterator.size_hint().0;
668-
let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
669-
set.extend(iterator);
666+
let mut set = HashSet::with_hasher(Default::default());
667+
set.extend(iter);
670668
set
671669
}
672670
}
@@ -677,9 +675,7 @@ impl<T, S> Extend<T> for HashSet<T, S>
677675
S: BuildHasher
678676
{
679677
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
680-
for k in iter {
681-
self.insert(k);
682-
}
678+
self.map.extend(iter.into_iter().map(|k| (k, ())));
683679
}
684680
}
685681

0 commit comments

Comments
 (0)