about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCheng XU <git@xuc.me>2021-08-28 16:57:58 -0700
committerCheng XU <git@xuc.me>2021-08-28 17:19:07 -0700
commita03287bbf765ce7ac0e2ae9e64d8ade168ece301 (patch)
tree03d6e4dd77936de49c41a8570aee2d28c03b1490
parentcf814d60f82723e5965763859c51b3e7bd885b9b (diff)
downloadrust-a03287bbf765ce7ac0e2ae9e64d8ade168ece301.tar.gz
rust-a03287bbf765ce7ac0e2ae9e64d8ade168ece301.zip
BTreeSet::from_iter: use bulk building to improve the performance
Apply the same optimization as BTreeMap::from_iter.
-rw-r--r--library/alloc/src/collections/btree/set.rs27
1 files changed, 22 insertions, 5 deletions
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 0c268ad32b2..fca281a63bb 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -1,6 +1,7 @@
 // This is pretty much entirely stolen from TreeSet, since BTreeMap has an identical interface
 // to TreeMap
 
+use crate::vec::Vec;
 use core::borrow::Borrow;
 use core::cmp::Ordering::{Equal, Greater, Less};
 use core::cmp::{max, min};
@@ -1059,9 +1060,17 @@ impl<T> BTreeSet<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> FromIterator<T> for BTreeSet<T> {
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> BTreeSet<T> {
-        let mut set = BTreeSet::new();
-        set.extend(iter);
-        set
+        let mut inputs: Vec<_> = iter.into_iter().collect();
+
+        if inputs.is_empty() {
+            return BTreeSet::new();
+        }
+
+        // use stable sort to preserve the insertion order.
+        inputs.sort();
+        let iter = inputs.into_iter().map(|k| (k, ()));
+        let map = BTreeMap::bulk_build_from_sorted_iter(iter);
+        BTreeSet { map }
     }
 }
 
@@ -1074,8 +1083,16 @@ impl<T: Ord, const N: usize> From<[T; N]> for BTreeSet<T> {
     /// let set2: BTreeSet<_> = [1, 2, 3, 4].into();
     /// assert_eq!(set1, set2);
     /// ```
-    fn from(arr: [T; N]) -> Self {
-        core::array::IntoIter::new(arr).collect()
+    fn from(mut arr: [T; N]) -> Self {
+        if N == 0 {
+            return BTreeSet::new();
+        }
+
+        // use stable sort to preserve the insertion order.
+        arr.sort();
+        let iter = core::array::IntoIter::new(arr).map(|k| (k, ()));
+        let map = BTreeMap::bulk_build_from_sorted_iter(iter);
+        BTreeSet { map }
     }
 }