0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Stream的核心概念

科技綠洲 ? 來源:TinyZ ? 作者:TinyZ ? 2023-09-19 16:19 ? 次閱讀

Stream 是 Rust 語言中的一種迭代器,它可以使得我們在處理數(shù)據時更加高效、靈活。Stream 不僅可以處理大量數(shù)據,還可以進行異步操作,這使得它在處理網絡請求等 IO 操作時非常有用。

Stream 的核心概念是將數(shù)據視為流,每次處理一個元素,而不是將整個數(shù)據集加載到內存中。這樣可以避免內存占用過大的問題,同時也能夠提高程序的效率。

基礎用法

創(chuàng)建 Stream

在 Rust 中,我們可以使用iter方法來創(chuàng)建 Stream。例如,我們可以使用以下代碼來創(chuàng)建一個包含 1 到 5 的 Stream:

let stream = (1..5).into_iter();

這里使用了into_iter方法將一個范圍轉換為 Stream。

遍歷 Stream

遍歷 Stream 可以使用for_each方法,例如:

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

這里使用了閉包來打印每個元素。

過濾 Stream

我們可以使用filter方法來過濾 Stream 中的元素,例如:

let stream = (1..5).into_iter().filter(|x| x % 2 == 0);

這里使用了閉包來判斷元素是否為偶數(shù)。

映射 Stream

我們可以使用map方法來對 Stream 中的元素進行映射,例如:

let stream = (1..5).into_iter().map(|x| x * 2);

這里使用了閉包來將每個元素乘以 2。

合并 Stream

我們可以使用chain方法來合并多個 Stream,例如:

let stream1 = (1..3).into_iter();
let stream2 = (4..6).into_iter();
let stream = stream1.chain(stream2);

這里使用了chain方法將兩個 Stream 合并為一個。

排序 Stream

我們可以使用sorted方法來對 Stream 中的元素進行排序,例如:

let stream = vec![3, 1, 4, 1, 5, 9].into_iter().sorted();

這里使用了sorted方法將 Stream 中的元素按照升序排序。

取前 n 個元素

我們可以使用take方法來取 Stream 中的前 n 個元素,例如:

let stream = (1..5).into_iter().take(3);

這里使用了take方法取 Stream 中的前 3 個元素。

跳過前 n 個元素

我們可以使用skip方法來跳過 Stream 中的前 n 個元素,例如:

let stream = (1..5).into_iter().skip(2);

這里使用了skip方法跳過 Stream 中的前 2 個元素。

統(tǒng)計元素個數(shù)

我們可以使用count方法來統(tǒng)計 Stream 中的元素個數(shù),例如:

let stream = (1..5).into_iter();
let count = stream.count();
println!("{}", count);

這里使用了count方法統(tǒng)計 Stream 中的元素個數(shù),并打印出來。

進階用法

異步 Stream

在 Rust 中,我們可以使用futures庫來創(chuàng)建異步 Stream。例如,我們可以使用以下代碼來創(chuàng)建一個異步 Stream:

use futures::stream::StreamExt;

let stream = futures::stream::iter(vec![1, 2, 3]);

這里使用了iter方法來創(chuàng)建一個包含 1 到 3 的異步 Stream。

并行 Stream

在 Rust 中,我們可以使用rayon庫來創(chuàng)建并行 Stream。例如,我們可以使用以下代碼來創(chuàng)建一個并行 Stream:

rayon = "1.7"
use rayon::iter::ParallelIterator;

let stream = (1..5).into_par_iter();

這里使用了into_par_iter方法將一個范圍轉換為并行 Stream。

處理 Stream 中的錯誤

在處理 Stream 時,有時候會出現(xiàn)錯誤。我們可以使用Result來處理這些錯誤。例如,我們可以使用以下代碼來處理 Stream 中的錯誤:

let stream = vec![1, 2, "a", 3].into_iter().map(|x| {
    if let Some(y) = x.downcast_ref::< i32 >() {
        Ok(*y)
    } else {
        Err("not a number")
    }
});

for item in stream {
    match item {
        Ok(x) = > println!("{}", x),
        Err(e) = > println!("{}", e),
    }
}

這里使用了downcast_ref方法將元素轉換為i32類型,如果轉換失敗則返回錯誤。

無限 Stream

在 Rust 中,我們可以使用repeat方法來創(chuàng)建一個無限 Stream。例如,我們可以使用以下代碼來創(chuàng)建一個包含無限個 1 的 Stream:

let stream = std::iter::repeat(1);

這里使用了repeat方法將 1 重復無限次。

處理 Stream 中的重復元素

在處理 Stream 時,有時候會出現(xiàn)重復元素的情況。我們可以使用dedup方法來去除 Stream 中的重復元素。例如:

let stream = vec![1, 2, 2, 3, 3, 3].into_iter().dedup();

這里使用了dedup方法去除 Stream 中的重復元素。

處理 Stream 中的空元素

在處理 Stream 時,有時候會出現(xiàn)空元素的情況。我們可以使用filter方法來過濾掉 Stream 中的空元素。例如:

let stream = vec![1, 2, "", 3, "", ""].into_iter().filter(|x| !x.is_empty());

這里使用了filter方法過濾掉 Stream 中的空元素。

處理 Stream 中的 None 值

在處理 Stream 時,有時候會出現(xiàn) None 值的情況。我們可以使用filter_map方法來過濾掉 Stream 中的 None 值。例如:

let stream = vec![Some(1), None, Some(2), None, Some(3)].into_iter().filter_map(|x| x);

這里使用了filter_map方法過濾掉 Stream 中的 None 值。

處理 Stream 中的重復元素

在處理 Stream 時,有時候會出現(xiàn)重復元素的情況。我們可以使用dedup_by方法來去除 Stream 中的重復元素。例如:

let stream = vec!["a", "b", "bc", "cd", "de", "ef"].into_iter().dedup_by(|a, b| a.chars().next() == b.chars().next());

這里使用了dedup_by方法去除 Stream 中的重復元素,去重條件是元素的首字母相同。

最佳實踐

在使用 Stream 時,我們應該注意以下幾點:

  • ? 盡量使用異步 Stream 來處理 IO 操作,這樣可以避免阻塞線程。
  • ? 在處理大量數(shù)據時,應該使用并行 Stream 來提高程序的效率。
  • ? 在處理錯誤時,應該使用Result來處理錯誤,避免程序崩潰。
  • ? 在處理無限 Stream 時,應該使用take方法限制 Stream 的大小,避免程序無限運行。
  • ? 在處理重復元素時,應該使用dedupdedup_by方法去除重復元素,避免重復計算。

示例代碼

下面是一個完整的示例代碼,演示了如何使用 Stream 來處理數(shù)據:

itertools = "0.10.5"
rayon = "1.7"
futures = "0.3.28"
use futures::stream::StreamExt;
use itertools::Itertools;
use rayon::iter::ParallelIterator;

fn main() {
    // 創(chuàng)建Stream
    let stream = (1..5).into_iter();

    // 遍歷Stream
    stream.for_each(|x| println!("{}", x));

    // 過濾Stream
    let stream = (1..5).into_iter().filter(|x| x % 2 == 0);
    stream.for_each(|x| println!("{}", x));

    // 映射Stream
    let stream = (1..5).into_iter().map(|x| x * 2);
    stream.for_each(|x| println!("{}", x));

    // 合并Stream
    let stream1 = (1..3).into_iter();
    let stream2 = (4..6).into_iter();
    let stream = stream1.chain(stream2);
    stream.for_each(|x| println!("{}", x));

    // 排序Stream
    let stream = vec![3, 1, 4, 1, 5, 9].into_iter().sorted();
    stream.for_each(|x| println!("{}", x));

    // 取前n個元素
    let stream = (1..5).into_iter().take(3);
    stream.for_each(|x| println!("{}", x));

    // 跳過前n個元素
    let stream = (1..5).into_iter().skip(2);
    stream.for_each(|x| println!("{}", x));

    // 統(tǒng)計元素個數(shù)
    let stream = (1..5).into_iter();
    let count = stream.count();
    println!("{}", count);

    // 異步Stream
    let stream = futures::stream::iter(vec![1, 2, 3]);
    futures::executor::block_on(async {
        stream.for_each(|x| async move {
            println!("{}", x);
        }).await;
    });

    // 并行Stream
    let stream = (1..5).into_par_iter();
    stream.for_each(|x| println!("{}", x));

    // 處理Stream中的錯誤
    let stream = vec![1, 2, "a", 3].into_iter().map(|x| {
        if let Some(y) = x.downcast_ref::< i32 >() {
            Ok(*y)
        } else {
            Err("not a number")
        }
    });

    for item in stream {
        match item {
            Ok(x) = > println!("{}", x),
            Err(e) = > println!("{}", e),
        }
    }

    // 無限Stream
    let stream = std::iter::repeat(1).take(5);
    stream.for_each(|x| println!("{}", x));

    // 處理Stream中的重復元素
    let stream = vec![1, 2, 2, 3, 3, 3].into_iter().dedup();
    stream.for_each(|x| println!("{}", x));

    // 處理Stream中的空元素
    let stream = vec![1, 2, "", 3, "", ""].into_iter().filter(|x| !x.is_empty());
    stream.for_each(|x| println!("{}", x));

    // 處理Stream中的None值
    let stream = vec![Some(1), None, Some(2), None, Some(3)].into_iter().filter_map(|x| x);
    stream.for_each(|x| println!("{}", x));

    // 處理Stream中的重復元素
    let stream = vec!["a", "b", "bc", "cd", "de", "ef"].into_iter().dedup_by(|a, b| a.chars().next() == b.chars().next());
    stream.for_each(|x| println!("{}", x));
}

總結

Stream 是 Rust 語言中非常重要的一個概念,它可以使得我們在處理數(shù)據時更加高效、靈活。在使用 Stream 時,我們應該注意異步、并行、錯誤處理、無限 Stream、重復元素等問題,這樣才能寫出高效、健壯的程序。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 數(shù)據
    +關注

    關注

    8

    文章

    6761

    瀏覽量

    88620
  • 代碼
    +關注

    關注

    30

    文章

    4697

    瀏覽量

    68086
  • Stream
    +關注

    關注

    0

    文章

    20

    瀏覽量

    7951
  • rust語言
    +關注

    關注

    0

    文章

    57

    瀏覽量

    2993
收藏 人收藏

    評論

    相關推薦

    Stream模塊的基礎用法和進階用法

    在 Rust 語言中,Tokio 是一個非常流行的異步編程框架。它提供了一系列的模塊,其中最常用的就是 Stream 模塊。Stream 模塊允許我們以異步的方式處理數(shù)據流,這在很多情況下非常
    的頭像 發(fā)表于 09-19 15:33 ?1087次閱讀

    Stream API原理介紹

    原理介紹 Stream API 的核心Stream 接口,它表示一組元素的序列,可以按需進行計算。Stream 接口提供了大量的中間操作和終端操作,可以用于過濾、映射、排序、聚合
    的頭像 發(fā)表于 09-30 15:31 ?643次閱讀

    Redis Stream應用案例

    摘要: Redis Stream Redis最新的大版本5.0已經RC1了,其中最重要的Feature莫過于Redis Stream了,關于Redis Stream的基本使用介紹和設計理念可以看我
    發(fā)表于 06-26 17:15

    請問BF60x中PVP編程stream是一個什么概念?

    1:stream 是一個什么概念。是不是特指PVP的輸入和輸出流?一個pvp的初始化過程只需要調用兩次adi_pvp_OpenStream?一次給輸入一次給輸出? 比如如下函數(shù)
    發(fā)表于 08-27 11:51

    請問AXI4-Stream到Video核心的技巧有什么?

    大家好。我遇到了xilinx視頻內核的問題,并試圖解決這個問題好幾周但都失敗了。有人能給我一些關于AXI4-Stream到Video核心的技巧嗎?我試圖在我的項目中實現(xiàn)Video Scaler核心
    發(fā)表于 11-08 09:53

    git的三個核心概念詳解

    git的三個核心概念(工作區(qū),版本庫stage,版本庫master)
    發(fā)表于 12-24 07:17

    AXI-stream數(shù)據傳輸過程

      AXI4-Stream跟AXI4的區(qū)別在于AXI4-Stream沒有ADDR接口,這樣就不涉及讀寫數(shù)據的概念了,只有簡單的發(fā)送與接收說法,減少了延時,允許無限制的數(shù)據突發(fā)傳輸規(guī)模
    發(fā)表于 01-08 16:52

    Media Stream Processor Environ

    MSP ConsortiumM.100 Revision 1.6Media Stream Processor EnvironmentSpecification This document
    發(fā)表于 06-26 10:10 ?15次下載

    AXI-Stream代碼

    AXI-Stream代碼詳解 AXI4-Stream跟AXI4的區(qū)別在于AXI4-Stream沒有ADDR接口,這樣就不涉及讀寫數(shù)據的概念了,只有簡單的發(fā)送與接收說法,減少了延時,允許
    的頭像 發(fā)表于 11-05 17:40 ?3431次閱讀
    AXI-<b class='flag-5'>Stream</b>代碼

    Kafka的核心概念

    Kafka 是主流的消息流系統(tǒng),其中的概念還是比較多的,下面通過圖示的方式來梳理一下 Kafka 的核心概念,以便在我們的頭腦中有一個清晰的認識。
    的頭像 發(fā)表于 06-20 14:24 ?905次閱讀

    關于AXI4-Stream協(xié)議總結分享

    XI4-Stream跟AXI4的區(qū)別就是AXI4-Stream去除了地址線,這樣就不涉及讀寫數(shù)據的概念了,只有簡單的發(fā)送與接收說法,減少了延時。由于AXI4-Stream協(xié)議(amba
    的頭像 發(fā)表于 06-23 10:08 ?2213次閱讀

    ARM SMMU Data structures之Stream Table

    incoming transaction的StreamID可以找到一個STE。SMMU支持兩種Stream table格式,格式由Stream table base registers設置。
    的頭像 發(fā)表于 05-11 09:22 ?1207次閱讀
    ARM SMMU Data structures之<b class='flag-5'>Stream</b> Table

    淺析Stream里的隱式轉換

    Stream、Flow是在電路描述里經常用到的對象。
    的頭像 發(fā)表于 05-15 17:36 ?432次閱讀
    淺析<b class='flag-5'>Stream</b>里的隱式轉換

    LogiCORE IP AXI4-Stream FIFO內核解決方案

    LogiCORE IP AXI4-Stream FIFO內核允許以內存映射方式訪問一個AXI4-Stream接口。該內核可用于與AXI4-Stream IP接口,類似于LogiCORE IP AXI以太網內核,而無需使用完整的D
    的頭像 發(fā)表于 09-25 10:55 ?1264次閱讀
    LogiCORE IP AXI4-<b class='flag-5'>Stream</b> FIFO內核解決方案

    Java的Stream的常用知識

    什么是Stream 生產線 Stream就像處理生產流水線一樣去工作,傳送帶就是Stream的管道,每個工廠關注直接的生產,將上游產品加工成下游需要的產品。為什么Stream比傳統(tǒng)的處
    的頭像 發(fā)表于 10-11 15:45 ?409次閱讀
    Java的<b class='flag-5'>Stream</b>的常用知識