当前位置: 首页 > news >正文

hashset

hashset说明

天然去除重复元素

创建和初始化

new

use std::collections::HashSet;fn main() {let mut set = HashSet::new();
}

查看容量和长度

use std::collections::HashSet;fn main() {let mut set: HashSet<i32> = HashSet::new();println!("初始容量: {}", set.capacity());println!("长度: {}", set.len());println!("是否为空: {}", set.is_empty());// 添加一些元素后再看容量set.insert(1);println!("插入1个元素后的容量: {}", set.capacity());set.insert(2);set.insert(3);println!("插入3个元素后的容量: {}", set.capacity());println!("长度: {}", set.len());
}
初始容量: 0
长度: 0
是否为空: true
插入1个元素后的容量: 3
插入3个元素后的容量: 3
长度: 3

with_capacity

使用with_capacity预分配容量(性能优化)

use std::collections::HashSet;fn main() {let mut set = HashSet::with_capacity(10);
}

请求容量测试

use std::collections::HashSet;fn main() {for requested in [1, 5, 10, 16, 20, 32] {let s: HashSet<i32> = HashSet::with_capacity(requested);println!("请求: {}, 实际: {}", requested, s.capacity());}
}
请求: 1, 实际: 3
请求: 5, 实际: 7
请求: 10, 实际: 14
请求: 16, 实际: 28
请求: 20, 实际: 28
请求: 32, 实际: 56

数组/vec创建

use std::collections::HashSet;fn main() {// 方式一: 使用from创建let set = HashSet::from([1, 2, 3]);// 方式二: 使用数组字面量创建let set: HashSet<_> = [1, 2, 3, 4].iter().cloned().collect();// Vec创建let v = vec![1, 2, 3];let set = HashSet::from(v); // v因为所有权已被转移
}

元组创建

需要展开为数组

use std::collections::HashSet;fn main() {let t = (1, 2, 3);// 方式一let set: HashSet<i32> = [t.0, t.1, t.2].iter().cloned().collect();// 方式二let set: HashSet<i32> = HashSet::from([t.0, t.1, t.2]);
}

切片创建

use std::collections::HashSet;fn main() {let slice: &[i32] = &[1, 2, 3, 4];let set: HashSet<i32> = slice.iter().cloned().collect();println!("{:?}", set)
}

操作元素

添加元素

insert会返回bool值,如果元素已经存在则返回false(添加失败)

use std::collections::HashSet;fn main() {let mut s = HashSet::new();let is_add = s.insert("a");println!("is_add: {}", is_add);println!("s: {:?}", s);
}
is_add: true
s: {"a"}

批量添加

s.extend(iter), 就地修改s集合,不创建新集合

use std::collections::HashSet;fn main() {let mut s = HashSet::new();s.extend(["a", "b", "c"]);s.extend(["a", "b", "2222"]); // a和b存在,就不会添加,之后添加2222println!("{:?}", s);
}
{"a", "b", "c", "2222"}

删除元素

s.remove(&value)返回bool值,如果元素不存在则返回false(删除失败)

use std::collections::HashSet;fn main() {let mut s1 = HashSet::from([1,2,3,4]);let is_del = s1.remove(&23); // 删除23失败,不存在println!("{}", is_del);println!("{:?}", s1);
}
false
{1, 3, 2, 4}

条件删除

s.retain(|x| x % 2 == 0): 保留偶数

use std::collections::HashSet;fn main() {let mut s1 = HashSet::from([1,2,3,4]);s1.retain(|&x| x % 2 == 0);println!("{:?}", s1)
}
{4, 2}

消费元素

s.take(&value): 删除并返回元素,返回Option<T>

use std::collections::HashSet;fn main() {let mut s = HashSet::from([1,2,3,4]);let v1 = s.take(&2);println!("v1: {:?}", v1);println!("s: {:?}", s);let v2 = s.take(&22);println!("v2: {:?}", v2);
}
v1: Some(2)
s: {1, 3, 4}
v2: None

查询

查询元素是否存在

set.contains(&value): 需要引用值

use std::collections::HashSet;fn main() {let s = HashSet::from([1,2,3,4]);let exists1 = s.contains(&2);println!("exists[2]: {}", exists1);let exists2 = s.contains(&0);println!("exists[0]: {}", exists2);
}
exists[2]: true
exists[0]: false

获取元素

set.get(&value): 需要引用值,返回一个Option<&T>

use std::collections::HashSet;fn main() {let mut s = HashSet::from([1,2,3,4]);let v1 = s.get(&2);println!("v1: {:?}", v1);println!("s: {:?}", s);let v2 = s.get(&22);println!("v2: {:?}", v2);
}
v1: Some(2)
s: {3, 1, 2, 4}
v2: None

元素数量

set.len()

use std::collections::HashSet;fn main() {let s1 = HashSet::from([1,2,3,4]);println!("s1: {}", s1.len());let s2:HashSet<i32> = HashSet::new();println!("s2: {}", s2.len());
}
s1: 4
s2: 0

set是否为空

set.is_empty()

use std::collections::HashSet;fn main() {let s1 = HashSet::from([1,2,3,4]);println!("s1: {}", s1.is_empty());let s2:HashSet<i32> = HashSet::new();println!("s2: {}", s2.is_empty());
}
s1: false
s2: true

迭代

HashSet的迭代顺序是不确定的

迭代所有元素

use std::collections::HashSet;fn main() {let mut s = HashSet::from([1,2,3,4]);// for i in &s// i是&i32类型for i in s.iter() {println!("{}", i);};print!("{:?}", s)
}
1
3
4
2
{1, 3, 4, 2}%

获取所有权

use std::collections::HashSet;fn main() {let mut s = HashSet::from([1,2,3,4]);// i是i32类型for i in s.into_iter() {println!("{}", i);};// print!("{:?}", s) // 不能再使用了,s已经被消费了
}
1
3
4
2

集合运算

unionintersectiondifferencesymmetric_difference,不会获取所有权.
它们接受引用参数&self&other_set

交集

a.intersection(&b)表示a在b中的元素

use std::collections::HashSet;fn main() {let a = HashSet::from([1,2,3]);let b = HashSet::from([2,3,4]);// 返回Intersection迭代器let c = a.intersection(&b);println!("{:?}", c);// 迭代器转为集合let c_set:HashSet<i32> = c.cloned().collect();println!("{:?}", c_set);
}
[3, 2]
{2, 3}

并集

a.union(&b)表示ab一起合并去重所有元素

use std::collections::HashSet;fn main() {let a = HashSet::from([1,2,3]);let b = HashSet::from([2,3,4]);// 返回Union迭代器let c = a.union(&b);println!("{:?}", c);// 迭代器转为集合let c_set:HashSet<i32> = c.cloned().collect();println!("{:?}", c_set);
}
[3, 1, 2, 4]
{2, 1, 3, 4}

差集

a.difference(&b)过滤出a没有在b中的元素

use std::collections::HashSet;fn main() {let a = HashSet::from([1,2,3]);let b = HashSet::from([2,3,4]);// 返回Difference迭代器let c = a.difference(&b);println!("{:?}", c);// 迭代器转为集合let c_set:HashSet<i32> = c.cloned().collect();println!("{:?}", c_set)
}
[1]
{1}

对称差集

a.symmetric_difference(&b)过滤出a和b中不重复的所有元素(包括b)

use std::collections::HashSet;fn main() {let a = HashSet::from([1,2,3]);let b = HashSet::from([2,3,4]);// 返回SymmetricDifference迭代器let c = a.symmetric_difference(&b);println!("{:?}", c);// 迭代器转为集合let c_set:HashSet<i32> = c.cloned().collect();println!("{:?}", c_set)
}
[1, 4]
{1, 4}

集合关系

子集

use std::collections::HashSet;fn main() {let a = HashSet::from([1, 2, 3, 4, 5]);let b = HashSet::from([2, 3, 4]);// 返回bool迭代器let s = b.is_subset(&a);println!("b是a的子集: {}", s)
}
b是a的子集: true

超集

use std::collections::HashSet;fn main() {let a = HashSet::from([1, 2, 3, 4, 5]);let b = HashSet::from([2, 3, 4]);// 返回bool迭代器let s = a.is_superset(&b);println!("a是b的超集: {}", s)
}
a是b的超集: true

不相交关系

两个集合没有公共元素

use std::collections::HashSet;fn main() {let a = HashSet::from([1, 2, 3, 4, 5]);let b = HashSet::from([21, 31, 41]);// 返回bool迭代器let s = a.is_disjoint(&b);println!("a和b不相交: {}", s)
}
a和b不相交: true

相等

use std::collections::HashSet;fn main() {let a = HashSet::from([1, 2, 3, 4, 5]);let b = HashSet::from([1, 2, 3, 4, 5]);println!("a和b相等: {}",  a == b);
}
a和b相等: true

自定义数据实现hash

HashSet需要元素实现

  • Hash - 计算哈希值,快速定位桶位置
  • PartialEq - 解决哈希冲突时比较是否真正相等
  • Eq - 标记 trait,保证相等关系的数学性质
use std::hash::{Hash, Hasher};
use std::collections::HashSet;#[derive(Debug)]
struct Key {id: u32,name: String,
}// 必须实现 Hash
impl Hash for Key {fn hash<H: Hasher>(&self, state: &mut H) {println!("  Hash::hash called for {:?}", self);self.id.hash(state);self.name.hash(state);}
}// 必须实现 PartialEq
impl PartialEq for Key {fn eq(&self, other: &Self) -> bool {println!("  PartialEq::eq called: {:?} vs {:?}", self, other);self.id == other.id && self.name == other.name}
}// 必须实现 Eq(标记 trait)
impl Eq for Key {}fn main() {let mut map = HashSet::new();println!("Inserting first key:");let key1 = Key { id: 1, name: "Alice".to_string() };map.insert(key1);let key2 = Key { id: 1, name: "Alice Modified".to_string() };map.insert(key2);println!("set: {:?}", map);
}
Inserting first key:Hash::hash called for Key { id: 1, name: "Alice" }Hash::hash called for Key { id: 1, name: "Alice Modified" }
set: {Key { id: 1, name: "Alice Modified" }, Key { id: 1, name: "Alice" }}
http://www.jsqmd.com/news/637154/

相关文章:

  • FPGA开发者的福音:用VS Code替代QuartusII_18.1默认编辑器的完整指南
  • VB.NET与BarTender.NET SDK集成:解决程序集加载失败与框架版本兼容性问题
  • SystemVerilog Assertions(SVA)用法以及帕拉丁emulation对SVA的支持情况总结
  • 别再让电机白费电了!手把手教你用MTPA算法在STM32上实现节能控制(附代码)
  • 电容是什么?一个“快充快放”的微型充电宝底
  • 机器人关节空间的轨迹规划
  • AI时代工程师的超级进化指南
  • 告别数据不准!用ESP32给MQ-135传感器做个“体检”与校准(附Python脚本)
  • 2025届必备的AI写作神器推荐
  • 2026年4月技术好的钢结构厂商推荐,国内钢结构精选优质厂家 - 品牌推荐师
  • 如何正确合并多个 Word 文档(.docx)并保留格式与分页
  • Android离屏渲染:从原理到性能优化的全景解析
  • 5分钟搞定UML类图:从关联到组合的实战代码对照
  • 2026最权威的十大AI论文方案解析与推荐
  • 电商系统的审计日志怎么设计?一次讲清谁改了什么、为什么改、出了问题怎么追
  • 2026年Java面试题集锦(含答案)
  • 导入Abaqus模块
  • 从冯·诺伊曼到杨振宁:那些改变世界的科学家们,他们的故事与精神遗产
  • 3步攻克3D协作难题:在线3D查看器如何重塑你的设计评审流程
  • std::io
  • ThreadPool 线程池参数到底怎么配才靠谱?一次讲清核心参数、任务模型与线上排查思路
  • 别再只用人脸识别了!头部姿态估计在智慧课堂与疲劳驾驶中的落地踩坑实录
  • PostgreSQL schema切换实战:5种方法设置search_path的适用场景与避坑指南
  • [具身智能-365]:LeRobot 与 ROS2 的关系,正如 PyTorch 与 Linux 在 AI 系统中的关系。
  • 西门子S7-200 PLC实战:手把手教你搭建自动扶梯节能控制系统(含变频器参数配置)
  • 携程旅行 token1005
  • 积分上限函数求导全攻略:常见误区与高效解法
  • 从浮点除法到三角函数优化:STM32F4的DSP库性能压测报告
  • 2025届学术党必备的AI辅助论文神器解析与推荐
  • 模型训练中的缩放法则:原理与实战应用全解析