Struct std::collections::HashSet
1.0.0 · source · pub struct HashSet<T, S = RandomState> { /* private fields */ }
Expand description
hash set,实现为 HashMap
,其中值为 ()
。
与 HashMap
类型一样,HashSet
要求元素实现 Eq
和 Hash
traits。这通常可以通过使用 #[derive(PartialEq, Eq, Hash)]
来实现。
如果您自己实现这些,那么拥有以下属性非常重要:
k1 == k2 -> hash(k1) == hash(k2)
换句话说,如果两个键相等,则它们的哈希值必须相等。
以这样一种方式修改键是一个逻辑错误,即键的哈希 (由 Hash
特征确定) 或其相等性 (由 Eq
特征确定) 在更改时发生变化在 map 上。
通常只有通过 Cell
,RefCell
,二进制状态,I/O 或不安全代码才能实现此操作。
此类逻辑错误导致的行为未指定,但会封装到观察到逻辑错误的 HashSet
中,不会导致未定义的行为。
这可能包括 panics、不正确的结果、中止、内存泄漏和未中止。
Examples
use std::collections::HashSet;
// 通过类型推断,我们可以省略显式类型签名 (在本示例中为 `HashSet<String>`)。
let mut books = HashSet::new();
// 添加一些书。
books.insert("A Dance With Dragons".to_string());
books.insert("To Kill a Mockingbird".to_string());
books.insert("The Odyssey".to_string());
books.insert("The Great Gatsby".to_string());
// 检查一个特定的。
if !books.contains("The Winds of Winter") {
println!("We have {} books, but The Winds of Winter ain't one.",
books.len());
}
// 删除一本书。
books.remove("The Odyssey");
// 遍历所有内容。
for book in &books {
println!("{book}");
}
Run将 HashSet
与自定义类型一起使用的最简单方法是派生 Eq
和 Hash
。我们还必须导出 PartialEq
,这将在 Eq
中隐含在 future 中。
use std::collections::HashSet;
#[derive(Hash, Eq, PartialEq, Debug)]
struct Viking {
name: String,
power: usize,
}
let mut vikings = HashSet::new();
vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
vikings.insert(Viking { name: "Olaf".to_string(), power: 4 });
vikings.insert(Viking { name: "Harald".to_string(), power: 8 });
// 使用派生的实现来打印 Viking。
for x in &vikings {
println!("{x:?}");
}
Run可以从数组初始化具有已知项列表的 HashSet
:
use std::collections::HashSet;
let viking_names = HashSet::from(["Einar", "Olaf", "Harald"]);
RunImplementations§
source§impl<T> HashSet<T, RandomState>
impl<T> HashSet<T, RandomState>
sourcepub fn new() -> HashSet<T, RandomState>
pub fn new() -> HashSet<T, RandomState>
sourcepub fn with_capacity(capacity: usize) -> HashSet<T, RandomState>
pub fn with_capacity(capacity: usize) -> HashSet<T, RandomState>
source§impl<T, S> HashSet<T, S>
impl<T, S> HashSet<T, S>
sourcepub fn iter(&self) -> Iter<'_, T> ⓘ
pub fn iter(&self) -> Iter<'_, T> ⓘ
一个迭代器,以任意顺序访问所有元素。
迭代器元素类型为 &'a T
。
Examples
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert("a");
set.insert("b");
// 将以任意顺序打印。
for x in set.iter() {
println!("{x}");
}
RunPerformance
在当前的实现中,迭代集合需要 O(capacity) 时间而不是 O(len) 时间,因为它在内部也访问了空的 buckets。
sourcepub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, T, F> ⓘwhere
F: FnMut(&T) -> bool,
🔬This is a nightly-only experimental API. (hash_drain_filter
#59618)
pub fn drain_filter<F>(&mut self, pred: F) -> DrainFilter<'_, T, F> ⓘwhere F: FnMut(&T) -> bool,
hash_drain_filter
#59618)创建一个迭代器,该迭代器使用闭包确定是否应删除值。
如果闭包返回 true,则该值将被删除并产生。 如果闭包返回 false,则该值将保留在列表中,并且不会由迭代器产生。
如果迭代器仅被部分消耗或根本没有消耗,则其余所有值仍将受到闭包的处理,如果返回 true,则将其删除并丢弃。
如果在闭包中出现 panic,或者在丢弃值时出现 panic,或者 DrainFilter
本身被泄漏,那么还有多少值将被关闭,这是未指定的。
Examples
将一个集合分为偶数和奇数值,重新使用原始集合:
#![feature(hash_drain_filter)]
use std::collections::HashSet;
let mut set: HashSet<i32> = (0..8).collect();
let drained: HashSet<i32> = set.drain_filter(|v| v % 2 == 0).collect();
let mut evens = drained.into_iter().collect::<Vec<_>>();
let mut odds = set.into_iter().collect::<Vec<_>>();
evens.sort();
odds.sort();
assert_eq!(evens, vec![0, 2, 4, 6]);
assert_eq!(odds, vec![1, 3, 5, 7]);
Run1.18.0 · sourcepub fn retain<F>(&mut self, f: F)where
F: FnMut(&T) -> bool,
pub fn retain<F>(&mut self, f: F)where F: FnMut(&T) -> bool,
仅保留谓词指定的元素。
换句话说,删除所有 f(&e)
返回 false
的 e
元素。
元素以未排序 (和未指定) 的顺序访问。
Examples
use std::collections::HashSet;
let mut set = HashSet::from([1, 2, 3, 4, 5, 6]);
set.retain(|&k| k % 2 == 0);
assert_eq!(set, HashSet::from([2, 4, 6]));
RunPerformance
在当前的实现中,这个操作需要 O(capacity) 时间而不是 O(len),因为它在内部也访问了空的 buckets。
1.7.0 (const: unstable) · sourcepub fn with_hasher(hasher: S) -> HashSet<T, S>
pub fn with_hasher(hasher: S) -> HashSet<T, S>
创建一个新的空哈希集,它将使用给定的哈希值来哈希键。
还使用默认的初始容量创建哈希集。
警告: hasher
通常是随机生成的,旨在允许 HashSet 抵抗导致许多冲突和非常差的性能的攻击。
使用此函数手动设置它可能会导致 DoS 攻击 vector。
传递的 hash_builder
应该为 HashMap 实现 BuildHasher
trait 才有用,有关详细信息,请参见其文档。
Examples
use std::collections::HashSet;
use std::collections::hash_map::RandomState;
let s = RandomState::new();
let mut set = HashSet::with_hasher(s);
set.insert(2);
Run1.7.0 · sourcepub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet<T, S>
pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet<T, S>
创建一个至少具有指定容量的空 HashSet
,使用 hasher
对键进行哈希处理。
哈希集将能够至少保留 capacity
个元素而无需重新分配。此方法允许分配比 capacity
更多的元素。
如果 capacity
为 0,则不会分配哈希集。
警告: hasher
通常是随机生成的,旨在允许 HashSet 抵抗导致许多冲突和非常差的性能的攻击。
使用此函数手动设置它可能会导致 DoS 攻击 vector。
传递的 hash_builder
应该为 HashMap 实现 BuildHasher
trait 才有用,有关详细信息,请参见其文档。
Examples
use std::collections::HashSet;
use std::collections::hash_map::RandomState;
let s = RandomState::new();
let mut set = HashSet::with_capacity_and_hasher(10, s);
set.insert(1);
Runsource§impl<T, S> HashSet<T, S>where
T: Eq + Hash,
S: BuildHasher,
impl<T, S> HashSet<T, S>where T: Eq + Hash, S: BuildHasher,
sourcepub fn reserve(&mut self, additional: usize)
pub fn reserve(&mut self, additional: usize)
保留至少 additional
个要插入 HashSet
中的更多元素的容量。集合可以保留更多空间来推测性地避免频繁的重新分配。
调用 reserve
后,容量将大于或等于 self.len() + additional
。
如果容量已经足够,则不执行任何操作。
Panics
如果新的分配大小溢出 usize
,就会出现 panics。
Examples
use std::collections::HashSet;
let mut set: HashSet<i32> = HashSet::new();
set.reserve(10);
assert!(set.capacity() >= 10);
Run1.57.0 · sourcepub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>
尝试为要插入到 HashSet
中的至少 additional
更多元素保留容量。集合可以保留更多空间来推测性地避免频繁的重新分配。
调用 try_reserve
后,如果返回 Ok(())
,容量将大于等于 self.len() + additional
。
如果容量已经足够,则不执行任何操作。
Errors
如果容量溢出,或者分配器报告失败,则返回错误。
Examples
use std::collections::HashSet;
let mut set: HashSet<i32> = HashSet::new();
set.try_reserve(10).expect("why is the test harness OOMing on a handful of bytes?");
Runsourcepub fn shrink_to_fit(&mut self)
pub fn shrink_to_fit(&mut self)
1.56.0 · sourcepub fn shrink_to(&mut self, min_capacity: usize)
pub fn shrink_to(&mut self, min_capacity: usize)
将集合的容量降低一个下限。 它将降低不低于提供的限制,同时保持内部规则,并可能根据调整大小策略留下一些空间。
如果当前容量小于下限,则为无操作。
Examples
use std::collections::HashSet;
let mut set = HashSet::with_capacity(100);
set.insert(1);
set.insert(2);
assert!(set.capacity() >= 100);
set.shrink_to(10);
assert!(set.capacity() >= 10);
set.shrink_to(0);
assert!(set.capacity() >= 2);
Runsourcepub fn difference<'a>(
&'a self,
other: &'a HashSet<T, S>
) -> Difference<'a, T, S> ⓘ
pub fn difference<'a>( &'a self, other: &'a HashSet<T, S> ) -> Difference<'a, T, S> ⓘ
访问表示差异的值,即,在 self
中但不在 other
中的值。
Examples
use std::collections::HashSet;
let a = HashSet::from([1, 2, 3]);
let b = HashSet::from([4, 2, 3, 4]);
// 可以看作是 `a - b`。
for x in a.difference(&b) {
println!("{x}"); // 打印 1
}
let diff: HashSet<_> = a.difference(&b).collect();
assert_eq!(diff, [1].iter().collect());
// 请注意,差异不是对称的,并且 `b - a` 表示其他含义:
let diff: HashSet<_> = b.difference(&a).collect();
assert_eq!(diff, [4].iter().collect());
Runsourcepub fn symmetric_difference<'a>(
&'a self,
other: &'a HashSet<T, S>
) -> SymmetricDifference<'a, T, S> ⓘ
pub fn symmetric_difference<'a>( &'a self, other: &'a HashSet<T, S> ) -> SymmetricDifference<'a, T, S> ⓘ
访问代表对称差异的值,即 self
或 other
中的值,但不能同时存在于两者中。
Examples
use std::collections::HashSet;
let a = HashSet::from([1, 2, 3]);
let b = HashSet::from([4, 2, 3, 4]);
// 以任意顺序打印 1、4。
for x in a.symmetric_difference(&b) {
println!("{x}");
}
let diff1: HashSet<_> = a.symmetric_difference(&b).collect();
let diff2: HashSet<_> = b.symmetric_difference(&a).collect();
assert_eq!(diff1, diff2);
assert_eq!(diff1, [1, 4].iter().collect());
Runsourcepub fn intersection<'a>(
&'a self,
other: &'a HashSet<T, S>
) -> Intersection<'a, T, S> ⓘ
pub fn intersection<'a>( &'a self, other: &'a HashSet<T, S> ) -> Intersection<'a, T, S> ⓘ
访问表示相交的值,即 self
和 other
中的值。
当 self
和 other
中存在相等的元素时,生成的 Intersection
可能会引用其中一个。
如果 T
包含未通过其 Eq
实现进行比较的字段,并且可能在两组 T
的两个相等副本之间保持不同的值,则这可能是相关的。
Examples
use std::collections::HashSet;
let a = HashSet::from([1, 2, 3]);
let b = HashSet::from([4, 2, 3, 4]);
// 以任意顺序打印 2,3。
for x in a.intersection(&b) {
println!("{x}");
}
let intersection: HashSet<_> = a.intersection(&b).collect();
assert_eq!(intersection, [2, 3].iter().collect());
Runsourcepub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> ⓘ
pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> ⓘ
访问表示并集的值,即 self
或 other
中的所有值,没有重复项。
Examples
use std::collections::HashSet;
let a = HashSet::from([1, 2, 3]);
let b = HashSet::from([4, 2, 3, 4]);
// 以任意顺序打印 1、2、3、4。
for x in a.union(&b) {
println!("{x}");
}
let union: HashSet<_> = a.union(&b).collect();
assert_eq!(union, [1, 2, 3, 4].iter().collect());
Run1.9.0 · sourcepub fn get<Q>(&self, value: &Q) -> Option<&T>where
T: Borrow<Q>,
Q: Hash + Eq + ?Sized,
pub fn get<Q>(&self, value: &Q) -> Option<&T>where T: Borrow<Q>, Q: Hash + Eq + ?Sized,
sourcepub fn get_or_insert(&mut self, value: T) -> &T
🔬This is a nightly-only experimental API. (hash_set_entry
#60896)
pub fn get_or_insert(&mut self, value: T) -> &T
hash_set_entry
#60896)sourcepub fn get_or_insert_owned<Q>(&mut self, value: &Q) -> &Twhere
T: Borrow<Q>,
Q: Hash + Eq + ToOwned<Owned = T> + ?Sized,
🔬This is a nightly-only experimental API. (hash_set_entry
#60896)
pub fn get_or_insert_owned<Q>(&mut self, value: &Q) -> &Twhere T: Borrow<Q>, Q: Hash + Eq + ToOwned<Owned = T> + ?Sized,
hash_set_entry
#60896)如果不存在给定的 value
,则将其拥有的副本插入到集合中,然后对集合中的值返回引用。
Examples
#![feature(hash_set_entry)]
use std::collections::HashSet;
let mut set: HashSet<String> = ["cat", "dog", "horse"]
.iter().map(|&pet| pet.to_owned()).collect();
assert_eq!(set.len(), 3);
for &pet in &["cat", "dog", "fish"] {
let value = set.get_or_insert_owned(pet);
assert_eq!(value, pet);
}
assert_eq!(set.len(), 4); // 插入了新的 "fish"
Runsourcepub fn get_or_insert_with<Q, F>(&mut self, value: &Q, f: F) -> &Twhere
T: Borrow<Q>,
Q: Hash + Eq + ?Sized,
F: FnOnce(&Q) -> T,
🔬This is a nightly-only experimental API. (hash_set_entry
#60896)
pub fn get_or_insert_with<Q, F>(&mut self, value: &Q, f: F) -> &Twhere T: Borrow<Q>, Q: Hash + Eq + ?Sized, F: FnOnce(&Q) -> T,
hash_set_entry
#60896)如果不存在给定的 value
,则将从 f
计算得出的值插入到集合中,然后对集合中的值返回引用。
Examples
#![feature(hash_set_entry)]
use std::collections::HashSet;
let mut set: HashSet<String> = ["cat", "dog", "horse"]
.iter().map(|&pet| pet.to_owned()).collect();
assert_eq!(set.len(), 3);
for &pet in &["cat", "dog", "fish"] {
let value = set.get_or_insert_with(pet, str::to_owned);
assert_eq!(value, pet);
}
assert_eq!(set.len(), 4); // 插入了新的 "fish"
Runsourcepub fn is_disjoint(&self, other: &HashSet<T, S>) -> bool
pub fn is_disjoint(&self, other: &HashSet<T, S>) -> bool
sourcepub fn is_subset(&self, other: &HashSet<T, S>) -> bool
pub fn is_subset(&self, other: &HashSet<T, S>) -> bool
如果集合是另一个集合的子集,则返回 true
,即 other
至少包含 self
中的所有值。
Examples
use std::collections::HashSet;
let sup = HashSet::from([1, 2, 3]);
let mut set = HashSet::new();
assert_eq!(set.is_subset(&sup), true);
set.insert(2);
assert_eq!(set.is_subset(&sup), true);
set.insert(4);
assert_eq!(set.is_subset(&sup), false);
Runsourcepub fn is_superset(&self, other: &HashSet<T, S>) -> bool
pub fn is_superset(&self, other: &HashSet<T, S>) -> bool
如果集合是另一个集合的超集,则返回 true
,即 self
至少包含 other
中的所有值。
Examples
use std::collections::HashSet;
let sub = HashSet::from([1, 2]);
let mut set = HashSet::new();
assert_eq!(set.is_superset(&sub), false);
set.insert(0);
set.insert(1);
assert_eq!(set.is_superset(&sub), false);
set.insert(2);
assert_eq!(set.is_superset(&sub), true);
RunTrait Implementations§
source§impl<T, S> BitAnd<&HashSet<T, S>> for &HashSet<T, S>where
T: Eq + Hash + Clone,
S: BuildHasher + Default,
impl<T, S> BitAnd<&HashSet<T, S>> for &HashSet<T, S>where T: Eq + Hash + Clone, S: BuildHasher + Default,
source§impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>where
T: Eq + Hash + Clone,
S: BuildHasher + Default,
impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>where T: Eq + Hash + Clone, S: BuildHasher + Default,
source§fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S>
fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S>
返回 self
和 rhs
的并集作为新的 HashSet<T, S>
。
Examples
use std::collections::HashSet;
let a = HashSet::from([1, 2, 3]);
let b = HashSet::from([3, 4, 5]);
let set = &a | &b;
let mut i = 0;
let expected = [1, 2, 3, 4, 5];
for x in &set {
assert!(expected.contains(x));
i += 1;
}
assert_eq!(i, expected.len());
Runsource§impl<T, S> BitXor<&HashSet<T, S>> for &HashSet<T, S>where
T: Eq + Hash + Clone,
S: BuildHasher + Default,
impl<T, S> BitXor<&HashSet<T, S>> for &HashSet<T, S>where T: Eq + Hash + Clone, S: BuildHasher + Default,
1.4.0 · source§impl<'a, T, S> Extend<&'a T> for HashSet<T, S>where
T: 'a + Eq + Hash + Copy,
S: BuildHasher,
impl<'a, T, S> Extend<&'a T> for HashSet<T, S>where T: 'a + Eq + Hash + Copy, S: BuildHasher,
source§fn extend_one(&mut self, item: &'a T)
fn extend_one(&mut self, item: &'a T)
extend_one
#72631)source§impl<T, S> Extend<T> for HashSet<T, S>where
T: Eq + Hash,
S: BuildHasher,
impl<T, S> Extend<T> for HashSet<T, S>where T: Eq + Hash, S: BuildHasher,
source§fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I)
source§fn extend_one(&mut self, item: T)
fn extend_one(&mut self, item: T)
extend_one
#72631)source§impl<T, S> FromIterator<T> for HashSet<T, S>where
T: Eq + Hash,
S: BuildHasher + Default,
impl<T, S> FromIterator<T> for HashSet<T, S>where T: Eq + Hash, S: BuildHasher + Default,
source§impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
source§impl<T, S> IntoIterator for HashSet<T, S>
impl<T, S> IntoIterator for HashSet<T, S>
source§fn into_iter(self) -> IntoIter<T> ⓘ
fn into_iter(self) -> IntoIter<T> ⓘ
创建一个消耗迭代器,即将每个值以任意顺序移出集合的迭代器。 调用此设置后将无法使用该设置。
Examples
use std::collections::HashSet;
let mut set = HashSet::new();
set.insert("a".to_string());
set.insert("b".to_string());
// 不能与常规 `.iter()` 一起收集到 Vec<String>。
let v: Vec<String> = set.into_iter().collect();
// 将以任意顺序打印。
for x in &v {
println!("{x}");
}
Run