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

【Rust迭代器】Rust迭代器用法解析与应用实战

在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Rust开发,Python全栈,Golang开发,云原生开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。

所属的专栏:Rust语言通关之路
景天的主页:景天科技苑

在这里插入图片描述

文章目录

  • Rust迭代器
    • 1. 迭代器基础
      • 1.1 什么是迭代器
      • 1.2 创建迭代器
      • 1.3 使用迭代器
    • 2. 迭代器适配器
      • 2.1 map
      • 2.2 filter
      • 2.3 filter_map
      • 2.4 flat_map
      • 2.5 take和take_while
      • 2.6 skip和skip_while
      • 2.7 zip
      • 2.8 enumerate
      • 2.9 chain
      • 2.10 cycle
    • 3. 消费迭代适配器
      • 3.1 collect
      • 3.2 fold
      • 3.3 any和all
      • 3.4 find和position
      • 3.6 max和min
      • 3.7 sum和product
      • 3.8 count
      • 3.9 last和nth
    • 4. 高级迭代器用法
      • 4.1 自定义迭代器
      • 4.2 Peekable迭代器
      • 4.3 迭代器性能
      • 4.4 并行迭代器
    • 5. 迭代器性能优化技巧
      • 1)避免中间集合:尽量使用迭代器链而不是创建中间集合
      • 2)使用for_each代替for循环:在某些情况下可能更高效
      • 3)利用短路求值:any和all会在确定结果后立即停止迭代
      • 4)选择合适的迭代器:根据需求选择iter()、iter_mut()或into_iter()
      • 5)预分配空间:当最终需要集合时,可以预分配空间提高性能
    • 6. 常见问题与解决方案
      • 1)迭代器被消耗:迭代器是消耗性的,一旦遍历完成就不能再使用
      • 2)所有权问题:into_iter()会获取所有权
      • 3)无限迭代器:某些迭代器(如cycle)是无限的,需要与take等适配器一起使用
      • 4)惰性求值:迭代器是惰性的,只有在消费者调用时才会执行
    • 7. 总结

Rust迭代器

迭代器是Rust语言中一个强大且高效的概念,它为处理集合和数据序列提供了统一、安全且零成本抽象的接口。
Rust的迭代器不仅使用方便,而且在编译时就能进行大量优化,使得最终生成的代码性能通常能与手写的循环相媲美。
迭代器模式允许你对一个项的序列进行某些处理。迭代器(iterator)负责遍历序列中的每一项和决定序列何时结束的逻辑。
当使用迭代器时,我们无需重新实现这些逻辑。

1. 迭代器基础

1.1 什么是迭代器

在Rust中,迭代器是实现了Iterator trait的任何类型都是迭代器。这个Iterator trait是标准库中的trait。源码中,这个trait定义如下:

pub trait Iterator {type Item;//type Item和Self::Item这种用法叫做定义trait的关联类型。这个在项目中用的比较多。这个next方法是被要求实现该trait唯一必须要实现的方法,该trait的其他方法是有默认实现fn next(&mut self) -> Option<Self::Item>; // 提供了许多默认方法...
}

next方法是被要求实现该trait唯一必须要实现的方法,该trait的其他方法是有默认实现
实例对象每调用一次next方法,返回一个元素,当迭代器结束时,返回None。
任何实现了Iterator trait的类型都可以被迭代,产生一系列值。

1.2 创建迭代器

Rust中的大多数集合类型都提供了创建迭代器的方法:

fn main() {// 创建迭代器,迭代器是实现了Iterator trait的对象// 通过集合创建迭代器let mut vec = vec![1, 2, 3];// 获取不可变引用迭代器let iter = vec.iter(); // 产生 &i32// 获取可变引用迭代器let iter_mut = vec.iter_mut(); // 产生 &mut i32// 获取所有权迭代器let into_iter = vec.into_iter(); // 产生 i32
}

创建可变引用迭代器

//创建mutable迭代器
let mut vec = vec![1, 2, 3];
for num in vec.iter_mut() {*num += 1;println!("{}", num);
}

在这里插入图片描述

创建获取所有权迭代器

//创建获取所有权的迭代器
let vec = vec![1, 2, 3];
for num in vec.into_iter() {println!("{}", num);
}
println!("{:?}", vec); // 错误!vec的所有权已移动到迭代器中

在这里插入图片描述

在 Rust 中,迭代器是 惰性的(lazy),这意味着直到调用方法消费迭代器之前它都不会有效果。

1.3 使用迭代器

创建迭代器之后,可以选择用多种方式利用它。
最简单的使用方式是for循环:

fn main() {let vec = vec![1, 2, 3];//使用迭代器for num in vec.iter() {println!("{}", num);}
}

在这里插入图片描述

使用for_each代替for循环:在某些情况下可能更高效

//for_each
let nums = vec![1, 2, 3, 4, 5];
//for_each方法会遍历迭代器中的所有元素,并对每个元素执行闭包
nums.iter().for_each(|x| println!("{}", x));

在这里插入图片描述

也可以手动调用next()方法:
返回的是Option
在这里插入图片描述

let mut iter = vec![1, 2, 3].iter();
//手动调用next方法
println!("{:?}", iter.next());
println!("{:?}", iter.next());
println!("{:?}", iter.next());
println!("{:?}", iter.next());

当迭代器结束时,返回None
在这里插入图片描述

2. 迭代器适配器

Rust提供了丰富的迭代器适配器方法,可以对迭代器进行各种转换和组合。

2.1 map

map对每个元素应用一个函数:
let nums = vec![1, 2, 3];
let squares: Vec<_> = nums.iter().map(|x| x * x).collect();
println!("{:?}", squares);

在这里插入图片描述

2.2 filter

filter只保留满足条件的元素:

let nums = vec![1, 2, 3, 4, 5];
let evens: Vec<_> = nums.iter().filter(|x| *x % 2 == 0).collect();
println!("{:?}", evens);

在这里插入图片描述

2.3 filter_map

结合了filter和map的功能:
filter_map 会调用 parse 方法,如果成功则返回 Some,失败则返回 None

let strings = vec!["3", "seven", "8", "nine"];
let numbers: Vec<i32> = strings.iter().filter_map(|s| s.parse().ok()).collect();
println!("{:?}", numbers);

在这里插入图片描述

2.4 flat_map

将每个元素转换为迭代器后展平
flat_map 会将每个单词的字符展开成一个迭代器,然后将这些迭代器连接起来

let words = vec!["hello", "world"];
let letters: Vec<_> = words.iter().flat_map(|w| w.chars()).collect();
println!("{:?}", letters);

在这里插入图片描述

2.5 take和take_while

take获取前n个元素:
在Rust中,Iterator 类型的 take(n) 方法是用来创建一个新的迭代器,这个新的迭代器将只包含原始迭代器的前 n 个元素。这意味着原始迭代器不会被消耗掉,你可以在之后再次使用它。

//take
let numbers = vec![1, 2, 3, 4, 5];// 使用 take 方法,获取前3个元素
let iter = numbers.iter().take(3);// 遍历新的迭代器
for number in iter {println!("{}", number);
}// 原始迭代器仍然可以再次使用
for number in numbers.iter() {println!("{}", number);
}

在这里插入图片描述

take_while获取满足条件的连续元素:

//take_while
let numbers = vec![1, 2, 3, 4, 5];// 使用 take_while 方法,获取满足条件小于3的元素
// take_while 会返回一个新的迭代器,这个迭代器会从原始迭代器中获取元素,直到满足条件为止
let iter = numbers.iter().take_while(|x| **x < 3);// 遍历新的迭代器
for number in iter {println!("{}", number);
}

在这里插入图片描述

2.6 skip和skip_while

与take相反,跳过元素:

//skip
let numbers = vec![1, 2, 3, 4, 5];// 使用 skip 方法,跳过前3个元素
let iter = numbers.iter().skip(3);// 遍历新的迭代器
for number in iter {println!("{}", number);
}//skip_while
let numbers = vec![1, 2, 3, 4, 5];// 使用 skip_while 方法,跳过满足条件小于3的元素
let iter = numbers.iter().skip_while(|x| **x < 3);// 遍历新的迭代器
for number in iter {println!("{}", number);
}

在这里插入图片描述

2.7 zip

将两个迭代器合并为一个元组迭代器:

//zip
let numbers = vec![1, 2, 3, 4, 5];
let letters = vec!['a', 'b', 'c', 'd', 'e'];// 使用 zip 方法,将两个迭代器组合成一个元组迭代器
let iter = numbers.iter().zip(letters.iter());// 遍历新的迭代器
for (number, letter) in iter {println!("{} - {}", number, letter);
}

在这里插入图片描述

2.8 enumerate

为每个元素添加索引:

//enumerate
let numbers = vec![1, 2, 3, 4, 5];// 使用 enumerate 方法,获取索引和元素
let iter = numbers.iter().enumerate();// 遍历新的迭代器
for (index, number) in iter {println!("{} - {}", index, number);

在这里插入图片描述

2.9 chain

连接两个迭代器:
注意:chain只能连接相同类型的迭代器

//chain
//注意:chain只能连接相同类型的迭代器
let numbers = vec![1, 2, 3];
let letters = vec![4, 5, 6];// 使用 chain 方法,将两个迭代器连接起来
let iter = numbers.iter().chain(letters.iter());// 遍历新的迭代器
for item in iter {println!("{}", item);
}

在这里插入图片描述

2.10 cycle

无限循环迭代器:

//cycle
let numbers = vec![1, 2, 3];// 使用 cycle 方法,将迭代器循环起来
let iter = numbers.iter().cycle(); // cycle会无限循环迭代器// 遍历新的迭代器
for (index, item) in iter.enumerate() {//设置个退出条件,否则会无限循环if index > 10 {break;}println!("{}", item);
}

在这里插入图片描述

3. 消费迭代适配器

消费者是消耗迭代器并产生最终结果的方法。

3.1 collect

将迭代器转换为集合:

let nums = 1..=5;
let squared: Vec<i32> = nums.map(|x| x * x).collect();
println!("{:?}", squared);

在这里插入图片描述

3.2 fold

累积计算:

//fold
//fold求和
let nums = 1..=5;
let sum = nums.fold(0, |acc, x| acc + x);println!("{}", sum);//使用fold求平均值
let nums = vec![1, 2, 3, 4, 5];
let avg = nums.iter().fold(0.0, |acc, x| acc + (*x as f64)) / (nums.len() as f64);println!("{}", avg);

在这里插入图片描述

3.3 any和all

检查是否存在或所有元素满足条件:

//any
let nums = vec![1, 2, 3, 4, 5];
//any方法会返回true或false,表示迭代器中任意一个元素满足条件即可
let has_even = nums.iter().any(|x| x % 2 == 0);println!("{}", has_even);//all
//all方法会返回true或false,表示迭代器中所有元素都满足条件才返回true
let nums = vec![1, 2, 3, 4, 5];
let all_even = nums.iter().all(|x| x % 2 == 0);println!("{}", all_even);

在这里插入图片描述

3.4 find和position

find和position都会返回Option
查找元素:

//find 返回的是满足条件的元素的引用Option
let nums = vec![1, 2, 3, 4, 5];
//find方法会返回Option,表示迭代器中找到的第一个满足条件的元素
let first_even = nums.iter().find(|x| **x % 2 == 0);//find方法返回Option,所以需要使用unwrap_or_else来处理None的情况
let first_even = first_even.unwrap_or_else(|| &0);
println!("{:?}", first_even);//position。返回的是索引Option
let nums = vec![1, 2, 3, 4, 5];
//position方法会返回Option,表示迭代器中找到的第一个满足条件的元素的索引
let first_even_index = nums.iter().position(|x| *x % 2 == 0);//position方法返回Option,所以需要使用unwrap_or_else来处理None的情况
let first_even_index = first_even_index.unwrap_or_else(|| 0);
println!("{:?}", first_even_index);

在这里插入图片描述

3.6 max和min

查找最大最小值:
返回的也是Option

//max
let nums = vec![1, 2, 3, 4, 5];
//max方法会返回Option,表示迭代器中最大的元素
let max = nums.iter().max();//max方法返回Option,所以需要使用unwrap_or_else来处理None的情况
let max = max.unwrap_or_else(|| &0);
println!("{:?}", max);//min
let nums = vec![1, 2, 3, 4, 5];
//min方法会返回Option,表示迭代器中最小的元素
let min = nums.iter().min();//min方法返回Option,所以需要使用unwrap_or_else来处理None的情况
let min = min.unwrap_or_else(|| &0);
println!("{:?}", min);

在这里插入图片描述

3.7 sum和product

求和与求积:

//sum
let nums = vec![1, 2, 3, 4, 5];
//sum方法会返回迭代器中所有元素的和
let sum = nums.iter().sum::<i32>(); //sum方法需要指定返回值的类型,在变量处标注类型也可以
println!("{:?}", sum);//product
let nums = vec![1, 2, 3, 4, 5];
//product方法会返回迭代器中所有元素的积
let product = nums.iter().product::<i32>(); //product方法需要指定返回值的类型,在变量处标注类型也可以
println!("{:?}", product);

在这里插入图片描述

3.8 count

计算元素数量:

//count
let nums = vec![1, 2, 3, 4, 5];
//count方法会返回usize,表示迭代器中所有元素的数量
let count = nums.iter().count();
println!("{:?}", count);

在这里插入图片描述

3.9 last和nth

last: 表示获取迭代器中最后一个元素
nth: 表示获取迭代器中第n个元素,n表示索引位置

//last
let nums = vec![1, 2, 3, 4, 5];
//last方法会返回Option,表示迭代器中最后一个元素
let last = nums.iter().last();//last方法返回Option,所以需要使用unwrap_or_else来处理None的情况
let last = last.unwrap_or_else(|| &0);
println!("{:?}", last);//nth
let nums = vec![1, 2, 3, 4, 5];
//nth方法会返回Option,表示迭代器中第n个元素,n从0开始
let third = nums.iter().nth(2);//nth方法返回Option,所以需要使用unwrap_or_else来处理None的情况
let third = third.unwrap_or_else(|| &0);
println!("{:?}", third);

在这里插入图片描述

4. 高级迭代器用法

4.1 自定义迭代器

我们可以实现自己的迭代器类型:

//自定义迭代器
struct Counter {count: u32,max: u32,
}impl Counter {fn new(max: u32) -> Counter {Counter { count: 0, max }}
}
//自定义迭代器,只需要我们创建的类实现Iterator这个trait即可
impl Iterator for Counter {type Item = u32; //type Item = u32;表示迭代器中元素的类型,在trait中定义//next方法是Iterator trait中定义的,我们需要实现它//next方法的返回值是Option<Self::Item>,表示迭代器中下一个元素,如果迭代器中没有下一个元素,则返回None//next方法的参数是&mut self,表示迭代器的可变引用,因为迭代器需要在每次调用next方法时修改内部的状态//Self::Item表示迭代器中元素的类型,我们在上面定义为u32fn next(&mut self) -> Option<Self::Item> {//如果计数器小于最大值,则增加计数器并返回Some(self.count),否则返回Noneif self.count < self.max {self.count += 1;Some(self.count)} else {None}}
}
fn main() {//创建Counter实例,传的参数是最大值let counter = Counter::new(5);//for循环会自动调用迭代器的next方法,直到迭代器返回Nonefor num in counter {println!("{}", num);}
}

在这里插入图片描述

4.2 Peekable迭代器

peekable允许我们查看下一个元素而不消耗它:
eekable 是 Rust 迭代器的一个适配器方法,它可以将任何迭代器转换为可以"偷看"下一个元素的迭代器。
这个功能在很多场景下非常有用,特别是当你需要基于下一个元素的值来决定当前如何处理时。
基本用法

let mut iter = [1, 2, 3].iter().peekable();

主要使用场景

  1. 前瞻性处理(Look-ahead Processing)
    当需要根据下一个元素决定当前元素如何处理时:
let numbers = [1, 2, 3, 4, 5];
let mut iter = numbers.iter().peekable();while let Some(num) = iter.next() {if let Some(&&next_num) = iter.peek() {println!("当前: {}, 下一个: {}", num, next_num);} else {println!("当前: {}, 这是最后一个", num);}
}
  1. 合并连续重复项
    处理连续重复的元素:
fn dedup_adjacent<I: Iterator<Item = i32>>(iter: I) -> impl Iterator<Item = i32> {let mut peekable = iter.peekable();std::iter::from_fn(move || {while let Some(current) = peekable.next() {if peekable.peek() != Some(&current) {return Some(current);}}None})
}
  1. 解析器和词法分析器
    在编写解析器时经常需要前瞻:
fn tokenize(input: &str) -> Vec<Token> {let mut chars = input.chars().peekable();let mut tokens = Vec::new();while let Some(c) = chars.next() {match c {'0'..='9' => {let mut num = c.to_string();while let Some('0'..='9') = chars.peek() {num.push(chars.next().unwrap());}tokens.push(Token::Number(num.parse().unwrap()));}// 其他token处理...}}tokens
}
  1. 条件性跳过元素
    基于后续元素决定是否跳过当前元素:
let mut iter = [1, 2, 3, 4, 5].iter().peekable();
let mut result = Vec::new();while let Some(&num) = iter.next() {if num == 3 && iter.peek() == Some(&&4) {// 跳过3如果下一个是4continue;}result.push(num);
}
  1. 分隔符处理
    处理以特定模式分隔的数据:
fn split_by_double_newline(text: &str) -> Vec<&str> {let mut lines = text.lines().peekable();let mut paragraphs = Vec::new();let mut current = String::new();while let Some(line) = lines.next() {current.push_str(line);if lines.peek() == Some(&"") {paragraphs.push(current);current = String::new();lines.next(); // 跳过空行}}if !current.is_empty() {paragraphs.push(current);}paragraphs
}

Peekable的重要方法
Peekable 迭代器提供了几个特有方法:
1)peek() - 返回下一个元素的引用但不消耗它
if iter.peek() == Some(&value) { … }

2)next() - 返回下一个元素并且消耗它
let next = iter.next();

3)next_if() - 条件性消耗下一个元素
// 只有当下一个元素匹配谓词时才消耗它
while let Some(item) = iter.next_if(|&x| x > 5) { … }

4)next_if_eq() - 只有当下一个元素等于给定值时才消耗它
// 只有当下一个元素是5时才消耗它
if let Some(five) = iter.next_if_eq(&5) { … }

示例:

//peekable
let nums = vec![1, 2, 3, 4, 5];
//peekable方法会返回一个Peekable迭代器,这个迭代器可以预览下一个元素,但是不会消费下一个元素
let mut iter = nums.iter().peekable();//peek方法会返回Option,表示预览下一个元素,但是不会消费下一个元素
let next = iter.peek();
println!("{:?}", next);//next方法会返回Option,表示获取下一个元素,并消费这个元素
let next = iter.next();
println!("{:?}", next);//再次调用peek方法,会返回下一个元素的引用,因为上一次调用next方法已经消费了上一个元素
let next = iter.peek();
println!("{:?}", next);

在这里插入图片描述

4.3 迭代器性能

Rust迭代器是零成本抽象,编译器能将其优化为高效的代码。例如:
let sum: i32 = (1…=100).filter(|x| x % 2 == 0).sum();
编译器会将其优化为类似手写循环的代码,而不会有额外的开销。

4.4 并行迭代器

需要在项目中安装第三方库

cargo add rayon

在这里插入图片描述

使用rayon库可以实现并行迭代:

//并行迭代器
use rayon::prelude::*;
fn main() {//使用并行迭代器let sum: u128 = (1..=100000).into_par_iter().filter(|x| x % 2 == 0) //过滤出偶数.sum(); //求和println!("{}", sum);
}

在这里插入图片描述

5. 迭代器性能优化技巧

1)避免中间集合:尽量使用迭代器链而不是创建中间集合

// 不好
let filtered: Vec<_> = nums.iter().filter(|x| x % 2 == 0).collect();
let doubled: Vec<_> = filtered.iter().map(|x| x * 2).collect();// 好
let result: Vec<_> = nums.iter().filter(|x| x % 2 == 0).map(|x| x * 2).collect();

2)使用for_each代替for循环:在某些情况下可能更高效

(0..100).for_each(|x| println!("{}", x));

3)利用短路求值:any和all会在确定结果后立即停止迭代

4)选择合适的迭代器:根据需求选择iter()、iter_mut()或into_iter()

5)预分配空间:当最终需要集合时,可以预分配空间提高性能

let mut result = Vec::with_capacity(100);
(0..100).map(|x| x * 2).for_each(|x| result.push(x));

6. 常见问题与解决方案

1)迭代器被消耗:迭代器是消耗性的,一旦遍历完成就不能再使用

let mut iter = vec![1, 2, 3].into_iter();
iter.next();  // 消耗第一个元素
let sum: i32 = iter.sum();  // 只会计算剩下的元素

2)所有权问题:into_iter()会获取所有权

一旦使用了into_iter(),原数据将不可再使用
let vec = vec![1, 2, 3];
let iter = vec.into_iter();  // vec的所有权被转移
// 这里不能再使用vec

3)无限迭代器:某些迭代器(如cycle)是无限的,需要与take等适配器一起使用

let first_ten = (0..).cycle().take(10).collect::<Vec<_>>();

4)惰性求值:迭代器是惰性的,只有在消费者调用时才会执行

let iter = (0..10).map(|x| {println!("Processing {}", x);x * 2
});  // 这里不会打印任何东西let result: Vec<_> = iter.collect();  // 现在才会执行

7. 总结

Rust的迭代器是一个强大而灵活的工具,它提供了高效、安全的方式来处理各种数据序列。
通过本文的学习,相信大家应该已经掌握了迭代器的基本用法、各种适配器和消费者方法,以及如何在实际项目中应用它们。
迭代器不仅能写出更简洁、更表达性的代码,还能保持高性能,这是Rust语言"零成本抽象"哲学的重要体现。
记住,熟练掌握迭代器需要实践。尝试在你们自己的Rust项目中使用迭代器,开始时可能会遇到一些困难,但随着经验的积累,你会越来越欣赏它们带来的便利和效率。

相关文章:

【Rust迭代器】Rust迭代器用法解析与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…...

嵌入式学习笔记DAY23(树,哈希表)

一、树 1.树的概念 之前我们一直在谈的是一对一的线性结构&#xff0c;现实中&#xff0c;还存在很多一对多的情况需要处理&#xff0c;一对多的线性结构——树。 树的结点包括一个数据元素及若干指向其子树的分支&#xff0c;结点拥有的子树数称为结点的度。度为0的结点称为叶…...

操作系统————五种页面置换算法(OPT,FIFO,LRU,NRU,加强版NRU)大总结

❤️❤️❤️算法1&#xff1a;最佳置换算法&#xff08;OPT&#xff09; 算法思想&#xff1a; 值得注意的是这是一种理想型算法&#xff0c;实际上并不可能实现&#xff0c;读者需要注意 下面我们来解析一下它的原理&#xff1a; 我们假设有三个内存块&#xff0c;对于页面…...

数据结构(二) 线性表

一. 线性表 1.定义 线性表是由n(n>0)个具有相同数据类型的数据元素构成的有限序列。其中&#xff0c;元素之间通过顺序关系排列&#xff0c;每个元素有且只有一个直接前驱和一个直接后继(除首尾元素外) 二.线性表的顺序表示(顺序表) 1.存储方式 使用连续的内存空间(数组)存储…...

TS04:高性能四通道自动灵敏度校准电容触摸传感器

在现代电子设备中&#xff0c;电容触摸传感器的应用越来越广泛&#xff0c;而高性能的传感器芯片是实现良好用户体验的关键。 TS04 四通道电容触摸传感器&#xff0c;凭借其自动灵敏度校准功能和多种特性&#xff0c;成为理想的解决方案。本文将简要介绍 TS04 的主要特性、功能…...

鸿蒙 系统-安全-程序访问控制-应用权限管控

Ability Kit 提供了一种允许应用访问系统资源&#xff08;如&#xff1a;通讯录等&#xff09;和系统能力&#xff08;如&#xff1a;访问摄像头、麦克风等&#xff09;的通用权限访问方式&#xff0c;来保护系统数据&#xff08;包括用户个人数据&#xff09;或功能&#xff0…...

ArcGIS Pro 3.4 二次开发 - 框架

环境&#xff1a;ArcGIS Pro SDK 3.4 .NET 8 文章目录 框架1 框架1.1 如何在 DockPane 可见或隐藏时订阅和取消订阅事件1.2 执行命令1.3 设置当前工具1.4 激活选项卡1.5 激活/停用状态 - 修改条件1.6 判断应用程序是否繁忙1.7 获取应用程序主窗口1.8 关闭 ArcGIS Pro1.9 获取 …...

打破传统仓库管理困局:WMS如何重构出入库全流程

引言 在制造业与零售业高速发展的今天&#xff0c;仓库管理仍普遍面临效率低、错发漏发频发、库存数据滞后等痛点。人工登记导致30%的错单率&#xff0c;货位混乱让拣货耗时增加50%&#xff0c;而账实不符引发的二次采购成本更吞噬着企业利润。如何突破传统管理桎梏&#xff1…...

npm 安装时 SSL 证书过期问题笔记

问题描述: npm error code CERT_HAS_EXPIRED npm error errno CERT_HAS_EXPIRED npm error request to https://registry.npm.taobao.org/axios failed, reason: certificate has expired 这表明当前配置的 npm 镜像源&#xff08;淘宝镜像 https://registry.npm.taobao.org&…...

【大数据】MapReduce 编程-- PageRank--网页排名算法,用于衡量网页“重要性”-排序网页

PageRank 是 Google 创始人拉里佩奇&#xff08;Larry Page&#xff09;和谢尔盖布林&#xff08;Sergey Brin&#xff09;在 1998 年提出的一种网页排名算法&#xff0c;用于衡量网页“重要性”的一种方式。它是搜索引擎中用于排序网页的一种基础算法 一个网页越是被其他重要…...

Craw4AI:LLM友好的网页爬虫

GitHub&#xff1a;https://github.com/unclecode/crawl4ai 更多AI开源软件&#xff1a;发现分享好用的AI工具、AI开源软件、AI模型、AI变现 - 小众AI Crawl4AI旨在让网页爬取和数据提取变得简单而高效。无论构建复杂的 AI 应用程序还是增强大语言模型&#xff0c;Crawl4AI 都能…...

idea 安装飞算-javaAI 插件使用

文章目录 前言idea 安装飞算-javaAI 插件使用1. 介绍一下飞算-AI2. 安装使用 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的…...

Lombok

Lombok Lombok 是一个 Java 库&#xff0c;通过注解自动生成样板代码&#xff08;如 Getter/Setter、构造函数等&#xff09;&#xff0c;从而简化开发。在你提供的代码中&#xff0c;AllArgsConstructor 就是一个 Lombok 注解。以下是 Lombok 常用注解及其作用的详细说明&…...

起点与破圈

写了多年代码&#xff0c;我为什么开始转向算法&#xff0c;直到如今投身于大模型领域&#xff1f; 作为一名拥有 10 年经验的开发者&#xff0c;我的职业路径几乎覆盖了技术发展的多个阶段。从最早使用 Flask/Django 开发网站&#xff0c;到后来构建大数据系统、设计服务器架…...

基于AI的Web数据管道,使用n8n、Scrapeless和Claude

引言 在当今数据驱动的环境中&#xff0c;组织需要高效的方法来提取、处理和分析网络内容。传统的网络抓取面临着诸多挑战&#xff1a;反机器人保护、复杂的JavaScript渲染以及持续的维护需求。此外&#xff0c;理解非结构化的网络数据则需要复杂的处理能力。 本指南演示了如…...

7GB显存如何部署bf16精度的DeepSeek-R1 70B大模型?

构建RAG混合开发---PythonAIJavaEEVue.js前端的实践-CSDN博客 服务容错治理框架resilience4j&sentinel基础应用---微服务的限流/熔断/降级解决方案-CSDN博客 conda管理python环境-CSDN博客 快速搭建对象存储服务 - Minio&#xff0c;并解决临时地址暴露ip、短链接请求改…...

初识函数------了解函数的定义、函数的参数、函数的返回值、说明文档的书写、函数的嵌套使用、变量的作用域(全局变量与局部变量)

文章目录 一、什么是函数&#xff1f;二、函数定义与调用2.1 基本语法2.2 示例演示 三、函数参数详解3.1 位置参数3.2 默认参数3.3 可变参数3.4 关键字参数 四、返回值与文档说明4.1 返回多个值4.2 编写文档字符串 五、函数嵌套与作用域5.1 嵌套函数示例5.2 变量作用域5.3 glob…...

Java常见API文档(下)

格式化的时间形式的常用模式对应关系如下&#xff1a; 空参构造创造simdateformate对象&#xff0c;默认格式 练习.按照指定格式展示 package kl002;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;public class Date3 {publi…...

ubuntu 20.04 ping baidu.coom可以通,ping www.baidu.com不通 【DNS出现问题】解决方案

ping baidu.coom可以通&#xff0c;ping www.baidu.com不通【DNS出现问题】解决方案 检查IPV6是否有问题 # 1. 检查 IPv6 地址&#xff0c;记住网络接口的名称 ip -6 addr show# 2. 测试本地 IPv6&#xff0c;eth0换成自己的网络接口名称 ping6 ff02::1%eth0# 3. 检查路由 ip…...

Oracle 中 open_cursors 参数详解:原理、配置与性能测试

#Oracle #参数 # open_cursors #ORA-01000 在 Oracle 数据库的众多参数中&#xff0c;open_cursors是一个对应用程序性能和资源管理有着重要影响的参数。它直接关系到数据库与应用程序之间游标资源的使用与分配&#xff0c;合理配置open_cursors参数&#xff0c;能够避免应用程…...

线程调度与单例模式:wait、notify与懒汉模式解析

一.wait 和 notify&#xff08;等待 和 通知&#xff09; 引入 wait notify 就是为了能够从应用层面&#xff0c;干预到多个不同线程代码的执行顺序&#xff0c;可以让后执行的线程主动放弃被调度的机会&#xff0c;等先执行的线程完成后通知放弃调度的线程重新执行。 自助取…...

AGI大模型(27):LangChain向量存储

1 安装依赖 使用一个简单的本地向量存储 FAISS,首先需要安装它 pip install faiss-cpu -i https://pypi.tuna.tsinghua.edu.cn/simple pip install langchain_community==0.3.7 -i https://pypi.tuna.tsinghua.edu.cn/simple 由于演示过程中用到了爬虫,需要安装依赖库,如…...

Qwen3 - 0.6B与Bert文本分类实验:深度见解与性能剖析

Changelog [25/04/28] 新增Qwen3-0.6B在Ag_news数据集Zero-Shot的效果。新增Qwen3-0.6B线性层分类方法的效果。调整Bert训练参数&#xff08;epoch、eval_steps&#xff09;&#xff0c;以实现更细致的观察&#xff0c;避免严重过拟合的情况。 TODO&#xff1a; 利用Qwen3-0.6…...

Oracle 的 PGA_AGGREGATE_LIMIT 参数

Oracle 的 PGA_AGGREGATE_LIMIT 参数 基本概念 PGA_AGGREGATE_LIMIT 是 Oracle 数据库 12c 引入的一个重要内存管理参数&#xff0c;用于限制所有服务器进程使用的 PGA&#xff08;Program Global Area&#xff09;内存总量。 参数作用 硬性限制&#xff1a;设置 PGA 内存使…...

# idea 中如何将 java 项目打包成 jar 包?

idea 中如何将 java 项目打包成 jar 包&#xff1f; 例如如何将项目dzs168-dashboard-generate打包成 dzs168-dashboard-generate.jar 1、打开项目结构 Project Structure 在IDEA的顶部菜单栏中选择【File】&#xff0c;然后选择【Project Structure】&#xff08;或者使用快…...

JVM(Java 虚拟机)深度解析

JVM&#xff08;Java 虚拟机&#xff09;深度解析 作为 Java 生态系统的核心&#xff0c;JVM&#xff08;Java Virtual Machine&#xff09;是 Java 语言 "一次编写&#xff0c;到处运行" 的关键。它不仅是 Java 程序的运行环境&#xff0c;更是一个复杂的系统软件&…...

算法题(150):拼数

审题&#xff1a; 本题需要我们将数组中的数据经过排序&#xff0c;使得他们拼接后得到的数是所有拼接方案中最大的 思路&#xff1a; 方法一&#xff1a;排序贪心 贪心策略1&#xff1a;直接排序 如果我们直接按照数组数据的字典序进行排序&#xff0c;会导致部分情况出错 eg&…...

怎么样进行定性分析

本文章将教会你如何对实验结果进行定性分析&#xff0c;其需要一定的论文基础&#xff0c;文末有论文撰写小技巧&#xff0c;不想看基础原理的人可以直接调到文章末尾。 一、什么是定性分析 定性分析是一种在众多领域广泛应用的研究方法&#xff0c;它致力于对事物的性质、特…...

RLᵛ_ Better Test-Time Scaling by Unifying LLM Reasoners With Verifiers

RLᵛ: Better Test-Time Scaling by Unifying LLM Reasoners With Verifiers 在人工智能领域&#xff0c;大语言模型&#xff08;LLM&#xff09;的推理能力提升一直是研究热点。今天要解读的论文提出了一种全新的强化学习框架RLᵛ&#xff0c;通过融合推理与验证能力&#xf…...

关于百度地图JSAPI自定义标注的图标显示不完整的问题(其实只是因为图片尺寸问题)

下载了几个阿里矢量图标库里的图标作为百度地图的自定义图标&#xff0c;结果百度地图显示的图标一直不完整。下载的PNG图标已经被正常引入到前端代码&#xff0c;anchor也设置为了图标底部中心&#xff0c;结果还是显示不完整。 if (iconUrl) {const icon new mapClass.Icon(…...

海思22AP70集超强算力、4K60编解码与多元特性于一体的智能SoC可替代3559V200、3516AV300、3556A

嘿&#xff0c;朋友们&#xff01;在这个对视觉效果有着极致追求的时代&#xff0c;海思半导体带着满满的诚意&#xff0c;为大家呈上一款堪称惊艳的专业超高清智能网络录像机SoC——22AP70&#xff0c;它就像一颗闪耀的科技新星&#xff0c;即将在各个领域掀起一场视觉革命&am…...

网络协议之一根网线就能连接两台电脑?

写在前面 ~~~~ 如果有两台电脑&#xff0c;通过一根网线可以实现网络互通吗&#xff1f;三台电脑呢&#xff1f;N台电脑呢&#xff1f;本文就以此作为主线来看下吧&#xff01; 1&#xff1a;正文 ~~~~ 如标题&#xff0c;一根网线就能连接两台电脑&#xff1f;答案是肯定的&a…...

为 Windows 和 Ubuntu 中设定代理服务器的详细方法

有时下载大模型总是下载不出来&#xff0c;要配置代理才行 一、Windows代理设置 ① 系统全局代理设置 打开【设置】→【网络和Internet】→【代理】。 在【手动设置代理】下&#xff0c;打开开关&#xff0c;输入&#xff1a; 地址&#xff1a;10.10.10.215 端口&#xff1a;…...

cmd里可以使用npm,vscode里使用npm 报错

cmd里可以使用npm,vscode里使用npm 报错 报错提示原因解决方法 报错提示 npm : 无法加载文件 C:\Program Files\nodejs\npm.ps1&#xff0c;因为在此系 统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/ fwlink/?LinkID135170 中的 about_Executi…...

MySQL数据库基础 -- SQL 语句的分类,存储引擎

目录 1. 什么是数据库 2. 基本使用 2.1 进入 mysql 2.2 服务器、数据库以及表的关系 2.3 使用案例 2.4 数据逻辑存储 3. SQL 语句分类 4. 存储引擎 4.1 查看存储引擎 4.2 存储引擎的对比 1. 什么是数据库 安装完 MySQL 之后&#xff0c;会有 mysql 和 mysqld。 MySQL …...

设置windows10同时多用户登录方法

RDP wrapper 的版本更新停止在2017年&#xff0c; 找到网上其它大神更新的软件&#xff0c; 参考&#xff1a;RDPWrap v1.8.9.9 (Windows家庭版开启远程桌面、Server解除远程数量限制&#xff09; - 吾爱破解 - 52pojie.cn 我的需求是在离线环境中布置&#xff0c;方法是&…...

【hive】hive内存dump导出hprof文件

使用jmap -dump:live,formatb,file命令 hive-metastore-heap-eval.sh文件 # if want hiveserver2 ,should grep "org.apache.hive.service.server.HiveServer2" # get pid pidps -ef | grep "org.apache.hadoop.hive.metastore.HiveMetaStore" | grep &qu…...

专题讨论3:基于图的基本原理实现走迷宫问题

问题描述 迷宫通常以二维矩阵形式呈现&#xff0c;矩阵中的元素用 0 和 1 表示&#xff0c;其中 0 代表通路&#xff0c;1 代表墙壁 。存在特定的起点和终点坐标&#xff0c;目标是从起点出发&#xff0c;寻找一条能够到达终点的路径。 实现思路 将迷宫中的每个可通行单元格…...

Linux基础第四天

系统之间文件共享 想要实现两个不同的系统之间实现文件共享&#xff0c;最简单的一种方案就是设置VMware软件的共享文件夹&#xff0c;利用共享文件夹可以实现linux系统和windows系统之间的文件共享&#xff0c;这样就可以实现在windows系统上编辑程序&#xff0c;然后在linux系…...

eNSP中单臂路由器配置完整实验及命令解释

单臂路由器&#xff08;Router on a Stick&#xff09;是一种通过单个物理接口处理多个VLAN间路由的解决方案 单臂路由器通过以下方式工作&#xff1a; 交换机端口配置为Trunk模式&#xff0c;允许多个VLAN流量通过路由器子接口为每个VLAN创建虚拟接口每个子接口配置对应VLAN…...

TeaType 奶茶性格占卜机开发记录:一场俏皮的 UniApp 单页奇遇

我正在参加CodeBuddy「首席试玩官」内容创作大赛&#xff0c;本文所使用的 CodeBuddy 免费下载链接&#xff1a;腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 最近我突发奇想&#xff0c;想用 UniApp 做一个轻松又俏皮的小工具&#xff0c;叫做「TeaType 奶茶性格占卜机」…...

AI神经网络降噪 vs 传统单/双麦克风降噪的核心优势对比

1. 降噪原理的本质差异 对比维度传统单/双麦克风降噪AI神经网络降噪技术基础基于固定规则的信号处理&#xff08;如谱减法、维纳滤波&#xff09;基于深度学习的动态建模&#xff08;DNN/CNN/Transformer&#xff09;噪声样本依赖预设有限噪声类型训练数据覆盖数十万种真实环境…...

【Nginx学习笔记】:Fastapi服务部署单机Nginx配置说明

服务部署单机Nginx配置说明 服务.conf配置文件&#xff1a; upstream asr_backend {server 127.0.0.1:8010; }server {listen 80;server_name your_domain.com;location / {proxy_pass http://localhost:8000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remot…...

JAVA Web 期末速成

一、专业术语及名词 1. Web 的特点 定义&#xff1a;web 是分布在全世界&#xff0c;基于 HTTP 通信协议&#xff0c;存储在 Web 服务器中的所有相互链接的超文本集 Web 是一种分布式超媒体系统Web 是多媒体化 和 易于导航的Web 与平台无关Web 是动态、交互的 2. TCP/IP 结…...

iOS:重新定义移动交互,引领智能生活新潮流

在当今智能手机与移动设备充斥的时代&#xff0c;操作系统作为其 “灵魂”&#xff0c;掌控着用户体验的方方面面。iOS 系统&#xff0c;这一由苹果公司精心雕琢的杰作&#xff0c;自诞生起便以独特魅力与卓越性能&#xff0c;在移动操作系统领域独树一帜&#xff0c;深刻影响着…...

LabVIEW数据库使用说明

介绍LabVIEW如何在数据库中插入记录以及执行 SQL 查询&#xff0c;适用于对数据库进行数据管理和操作的场景。借助 Database Connectivity Toolkit&#xff0c;可便捷地与指定数据库交互。 各 VI 功能详述 左侧 VI 功能概述&#xff1a;实现向数据库表中插入数据的操作。当输入…...

Linux多进程 写时拷贝 物理地址和逻辑地址

如果不采用写时拷贝技术 直接fork子进程 会发生什么&#xff1f; 如上图所示 橙色为父进程所占内存空间 绿色为子进程所占内存空间。 如果子进程只是需要做出一点点和父进程不一样的 其余和父进程均为相同 第一 就会出现复制开销比较大&#xff1b;第二占用内存空间 所以 …...

在 CentOS 7.9 上部署 node_exporter 并接入 Prometheus + Grafana 实现主机监控

文章目录 在 CentOS 7.9 上部署 node_exporter 并接入 Prometheus Grafana 实现主机监控环境说明node_exporter 安装与配置下载并解压 node_exporter创建 Systemd 启动服务验证服务状态验证端口监听 Prometheus 配置 node_exporter 监控项修改 prometheus.yml重新加载 Prometh…...

Java 反射(Reflection)技术

反射是 Java 提供的一种强大机制&#xff0c;允许程序在运行时&#xff08;Runtime&#xff09;动态地获取类的信息、操作类的属性和方法。这种能力使得 Java 程序可以突破编译时的限制&#xff0c;实现更灵活的设计。 一、反射的核心概念 1. 什么是反射 反射是指在程序运行…...

【SpringBoot】从零开始全面解析SpringMVC (三)

本篇博客给大家带来的是SpringBoot的知识点, 本篇是SpringBoot入门, 介绍SpringMVC相关知识. &#x1f40e;文章专栏: JavaEE进阶 &#x1f680;若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,…...