about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorarthurprs <arthurprs@gmail.com>2016-11-26 17:30:29 +0100
committerarthurprs <arthurprs@gmail.com>2016-12-06 10:14:59 +0100
commit2c5d2403d770e624bbb0b9ce8e970efa914a8602 (patch)
treefe7f71e99197ae0bda628b3d99cf5b311255a268 /src/libstd
parent73e98a0210f0afdec28b4f5bc0f7327d6a5a8555 (diff)
downloadrust-2c5d2403d770e624bbb0b9ce8e970efa914a8602.tar.gz
rust-2c5d2403d770e624bbb0b9ce8e970efa914a8602.zip
Smarter HashMap/HashSet extend
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/collections/hash/map.rs17
-rw-r--r--src/libstd/collections/hash/set.rs10
2 files changed, 16 insertions, 11 deletions
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index ece51d6d826..9f9d0429fca 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -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);
         }
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 1ec7a4a7b63..72af612f569 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -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, ())));
     }
 }