20天學會rust(四)常見系統庫的使用

前面已經學習了rust的基礎知識,今天我們來學習rust強大的系統庫,從此coding事半功倍。

集合

數組&可變長數組

在 Rust 中,有兩種主要的數組類型:固定長度數組(Fixed-size Arrays)和可變長度數組(Dynamic-size Arrays)。

  1. 固定長度數組(Fixed-size Arrays):
    固定長度數組的長度在編譯時就確定,并且長度不可改變。你可以使用以下語法定義一個固定長度數組:
fn main() {let arr: [i32; 5] = [1, 2, 3, 4, 5];
}

在上面的例子中,我們定義了一個類型為 i32 的固定長度數組 arr ,長度為 5,并初始化了數組的元素。

  1. 可變長度數組(Dynamic-size Arrays):
    Rust 中沒有直接支持可變長度數組的語法。但是,你可以使用 Vec<T> 類型來創建一個動態增長的數組。 Vec<T> 是一個可變長度的動態數組,可以根據需要動態添加和刪除元素。以下是一個使用 Vec<T> 的示例:
fn main() {let mut vec: Vec<i32> = Vec::new();vec.push(1);vec.push(2);vec.push(3);
}

在上面的例子中,我們首先創建了一個空的 Vec<i32> ,然后使用 push 方法向數組中添加元素。 Vec<T> 會根據需要自動調整大小。

需要注意的是,可變長度數組( Vec<T> )和固定長度數組( [T; N] )是不同的類型,它們具有不同的性質和用途。下面我們再看下Vec的一些基礎用法:

創建Vec
在 Rust 中,有幾種創建 Vec 的方式:

  1. 使用 Vec::new() 創建一個空的 Vec:
let mut vec = Vec::new();

這會創建一個長度為 0 的空向量。

  1. 使用 vec![] 宏創建一個非空的 Vec:
let mut vec = vec![1, 2, 3];

這會創建一個長度為 3、值為 [1, 2, 3] 的可變數組。

  1. 使用 Vec::with_capacity() 創建一個指定容量的 Vec:
let mut vec = Vec::with_capacity(10);

這會創建一個長度為 0 但預分配了 10 個元素空間的向量。這意味著,在不重新分配內存的情況下,vec 可以增長到 10 個元素。

  1. 使用 iterator 方法創建一個 Vec:
let mut vec = (1..10).collect::<Vec<i32>>();

這會創建一個長度為 9、值為 [1, 2, 3, 4, 5, 6, 7, 8, 9] 的向量。

這些方法的主要區別在于:

  • Vec::new() 和 vec![] 創建的向量初始長度為 0 或指定長度。
  • Vec::with_capacity() 創建的向量初始長度為 0,但預分配了指定的容量。這可以提高向量在后續增長時的性能,因為不需要頻繁重新分配內存。
  • 使用 iterator 方法創建的向量會根據 iterator 的長度創建指定大小的向量。

總的來說,如果你知道向量的大致大小,使用 Vec::with_capacity() 可以獲得最好的性能。否則,Vec::new() 和 vec![] 也是不錯的選擇。這里的區別類似Java。

操作Vec
在 Rust 中, Vec<T> 是一個可變長度的動態數組,用于存儲相同類型的多個值。它有以下主要的方法:

  1. 添加元素 - 使用 push() 方法:
let mut vec = Vec::new();
vec.push(1);
  1. 刪除元素 - 使用 pop() 方法刪除最后一個元素:
let mut vec = vec![1, 2, 3];
vec.pop(); // vec = [1, 2]
  1. 查找元素 - 使用索引( [] )訪問元素:
let vec = vec![1, 2, 3];
let elem = vec[0]; // elem = 1
  1. 修改元素 - 也使用索引( [] )訪問元素,然后對其進行修改:
let mut vec = vec![1, 2, 3];
vec[0] = 5; 
// vec = [5, 2, 3]

除此之外, Vec<T> 還有其他方法,比如:

  • len() - 獲取向量長度
  • iter() - 創建一個迭代器以便于遍歷元素
  • iter_mut() - 創建一個可變迭代器以便于修改元素
  • first() - 獲取第一個元素
  • last() - 獲取最后一個元素
  • get() - 安全地訪問一個元素,返回 Option<&T>
  • get_mut() - 安全地訪問一個可變元素,返回 Option<&mut T>

這些方法可以滿足你對 Vec<T> 的基本操作需求。

map

在 Rust 中,有幾種主要的 map 實現:

  1. HashMap - 散列表映射,基于哈希表實現。這是 Rust 中最常用的映射類型。
  2. BTreeMap - 二叉樹映射,基于二叉樹實現。鍵值是有序的。
  3. LinkedHashMap - 鏈表散列表映射,基于哈希表和雙向鏈表實現。鍵值保持插入順序。
  4. IndexMap - 基于數組的映射。鍵必須實現 Index trait。
  5. FxHashMap - 散列表映射,使用第三方 fxhash 算法實現。性能可能優于標準庫的 HashMap

這里主要介紹HashMap的用法,其他的大同小異,后續會出一個專門的用法介紹。
在 Rust 中,HashMap 的主要用法如下:

  1. 創建一個空的 HashMap:
let mut map = HashMap::new();
  1. 插入鍵值對:
map.insert(1, "a");
  1. 獲取值:
let a = map.get(&1); // a = Some("a")
  1. 刪除鍵值對:
map.remove(&1);
  1. 迭代 HashMap:
for (key, value) in &map {println!("{}: {}", key, value);
}
  1. 檢查鍵是否存在:
map.contains_key(&1); // true 或 false
  1. 獲取 HashMap 的長度:
let len = map.len();
  1. 清空 HashMap:
map.clear();
  1. 只迭代鍵或值:
for key in map.keys() {println!("{}", key); 
}for value in map.values() {println!("{}", value);
}

這些是 HashMap 在 Rust 中最基本和最常用的方法。HashMap 是一個無序的 map,鍵類型必須實現 EqHash trait。

Set

  1. HashSet - 散列表集合,基于哈希表實現。用于存儲唯一的鍵。
  2. BTreeSet - 二叉樹集合,基于二叉樹實現。鍵值是有序的。

這里我們也重點介紹HashSet的用法:

  1. HashSet基礎用法:
let mut set = HashSet::new();
set.insert(1); // 插入元素:
set.remove(&1);// 刪除元素:
set.contains(&1); // 檢查元素是否存在: true 或 false
let len = set.len();// 獲取 HashSet 的長度:for elem in &set { // 迭代 HashSet:println!("{}", elem);
}set.clear(); // 清空 HashSet:
  1. 取兩個 HashSet 的交集、并集、差集:
let set1 = HashSet::from([1, 2, 3]);
let set2 = HashSet::from([2, 3, 4]);let intersection = set1.intersection(&set2).collect(); // [2, 3]
let union = set1.union(&set2).collect(); // [1, 2, 3, 4]
let difference = set1.difference(&set2).collect(); // [1]

HashSet 是一個無序的集合,元素類型必須實現 EqHash trait。

迭代器&流式編程(Iterator)

在 Rust 中,迭代器(Iterator)是一種用于遍歷集合元素的抽象。它提供了一個統一的接口,使你可以對各種不同類型的集合進行迭代。

要使用迭代器,你可以按照以下步驟進行操作:

  1. 創建一個迭代器:
    你可以通過調用集合上的 .iter().iter_mut() 方法來創建一個不可變或可變的迭代器。例如:
let vec = vec![1, 2, 3];
let iter = vec.iter(); // 不可變迭代器
let mut_iter = vec.iter_mut(); // 可變迭代器
  1. 使用迭代器方法:
    一旦你創建了迭代器,你可以使用迭代器的方法來處理集合的元素。一些常見的方法包括 .next().map().filter().fold() 等。例如:
let vec = vec![1, 2, 3];
let mut iter = vec.iter();// 使用 .next() 方法逐個獲取元素
while let Some(item) = iter.next() {println!("{}", item);
}// 使用 .map() 方法對元素進行轉換
let vec2: Vec<i32> = vec.iter().map(|x| x * 2).collect();
println!("{:?}", vec2); // 輸出 [2, 4, 6]// 使用 .filter() 方法過濾元素
let vec3: Vec<i32> = vec.iter().filter(|x| *x > 1).cloned().collect();
println!("{:?}", vec3); // 輸出 [2, 3]
  1. 鏈式調用迭代器方法:
    你可以使用鏈式調用來組合多個迭代器方法,以實現復雜的操作。例如:
let vec = vec![1, 2, 3];
let result: i32 = vec.iter().filter(|x| *x > 1).map(|x| x * 2).sum();
println!("{}", result); // 輸出 10

通過這些方法,你可以對集合進行各種操作,如過濾、映射、折疊等。

  1. 自定義迭代器

在 Rust 中,你可以通過實現 Iterator trait 來自定義迭代器。 Iterator trait 有以下定義:

trait Iterator {type Item;fn next(&mut self) -> Option<Self::Item>;// 默認方法fn size_hint(&self) -> (usize, Option<usize>) { ... }fn count(self) -> usize { ... }fn last(self) -> Option<Self::Item> { ... }fn nth(&mut self, n: usize) -> Option<Self::Item> { ... }fn step_by(self, step: usize) -> StepBy<Self> { ... }// 等等
}

要實現這個 trait,你需要:

  1. 定義 Item 類型,表示迭代器返回的元素類型。

  2. 實現 next 方法,返回迭代器的下一個元素,如果迭代器結束則返回 None

  3. 可選:實現其他默認方法來改善迭代器的行為。

以下是一個自定義迭代器的示例:

struct Counter {count: u32,
}impl Iterator for Counter {type Item = u32;fn next(&mut self) -> Option<Self::Item> {if self.count < 5 {let c = self.count;self.count += 1;Some(c)} else {None}}
}fn main() {let mut iter = Counter { count: 0 };while let Some(i) = iter.next() {println!("{}", i);}
}

這個迭代器會返回 0 到 4 的數字,然后結束。我們實現了 next 方法來定義這個行為。

通過實現 Iterator trait,你可以創建各種自定義的迭代器,以滿足不同的需求。希望這能幫助你理解 Rust 中的迭代器和如何自定義迭代器!如果還有其他問題,請隨時提問。

并發

多線程處理

下面我們通過一個例子學習: 創建一個線程,并每隔2s輸出“hello world”

上代碼:

use std::thread;
use std::time::Duration;fn main() {thread::spawn(|| {loop {println!("hello world");thread::sleep(Duration::from_secs(2));}});
}

這個代碼會:

  • 使用 thread::spawn 創建一個新線程
  • 在線程中有一個無限循環
  • 每次循環會打印 “hello world”
  • 使用 thread::sleep 使線程睡眠 2 秒
  • 所以這個線程會每隔 2 秒打印一次 “hello world”

Duration::from_secs(2) 是創建一個表示 2 秒的 Duration。我們將其傳遞給 thread::sleep 來使線程睡眠 2 秒。

Ok,我們掌握了線程的基礎用法, 再來看一個復雜的例子: 用多線程實現觀察者模式

要實現觀察者模式,可以使用通道(channel)在線程間通信。例如:

use std::sync::mpsc;
use std::thread;struct Subject {observers: Vec<mpsc::Sender<i32>>,
}impl Subject {fn new() -> Subject {Subject { observers: vec![] }}fn attach(&mut self, observer: mpsc::Sender<i32>) {self.observers.push(observer);}fn notify(&self) {for observer in self.observers.iter() {observer.send(1).unwrap();}}
}fn main() {let (tx1, rx1) = mpsc::channel();let (tx2, rx2) = mpsc::channel();let mut subject = Subject::new();subject.attach(tx1);subject.attach(tx2);thread::spawn(move || {let msg = rx1.recv().unwrap();println!("Got: {}", msg);});thread::spawn(move || {let msg = rx2.recv().unwrap();println!("Got: {}", msg);});subject.notify();
}

在這個例子中:

  • Subject 結構體充當主題(subject),維護多個觀察者(observers)的列表。
  • attach 方法用于添加觀察者(通道的發送端)。
  • notify 方法用于通知所有觀察者(通過通道發送消息)。
  • 我們創建兩個線程作為觀察者,通過通道接收主題的通知。
  • 當調用 subject.notify() 時,兩個觀察者線程會接收到通知并打印消息。

線程間通信

在上面的例子中,有一個新的知識點:使用通道(channel)在線程間通信。 那么什么是channel呢?

在 Rust 中,channel 用于在線程之間發送消息和通信。它可以在不同的線程之間安全地傳遞數據。

channel 的主要作用有:

  1. 線程間通信:channel 可以在不同的線程之間發送消息,用于線程間的通信和協作。

  2. 安全地共享數據:channel 可以在線程之間安全地傳遞數據,避免數據競爭。

  3. 限制并發:channel 的發送端和接收端各有一個緩存,這可以限制線程之間并發發送和接收消息的數量。

舉個例子:

use std::sync::mpsc::channel;
use std::thread;fn main() {let (tx, rx) = channel();thread::spawn(move || {tx.send(10).unwrap();});let received = rx.recv().unwrap();println!("Got: {}", received);
}

在這個例子中:

  • 我們使用 channel() 創建一個 channel,它返回一個發送端 tx 和一個接收端 rx
  • 然后我們創建一個線程,在線程中通過 tx 發送消息 10。
  • 在主線程中,我們通過 rx 接收該消息,并打印結果。
  • 這樣,通過 channel 我們就在兩個線程之間安全地傳遞了數據。

channel 在 Rust 的并發編程中非常有用,它可以用于線程池、工作竊取等并發模式中。
再看一個用法: 工作竊取

這里是一個使用 channel 實現工作竊取的例子:

use std::sync::mpsc::channel;
use std::thread;fn main() {let (tx, rx) = channel();let mut threads = vec![];for i in 0..10 {let tx = tx.clone();threads.push(thread::spawn(move || {let mut work = rx.recv().unwrap();while let Some(job) = work.recv() {println!("Worker {} got job {}", i, job);}}));}for job in 0..10 {let thread_id = job % threads.len();threads[thread_id].send(job).unwrap();}
}

這個例子做了以下工作:

  1. 創建一個 channel,得到發送端 tx 和接收端 rx。

  2. 創建 10 個工作線程,每個線程從 rx 接收工作。

  3. 將 10 個工作(job)發送到不同的工作線程,實現工作竊取。每個工作會被發送到線程 ID 與工作 ID 取余后的線程。

  4. 每個工作線程接收工作,并打印接收到的工作 ID。

  5. 主線程將所有工作分發完成后結束。

這個例子展示了如何使用 channel 在線程之間傳遞工作,實現工作竊取的模式。每個工作線程從 channel 接收工作,而不是固定的工作隊列。這使得工作可以在線程之間動態分配,實現工作竊取。

線程池

熟悉java的同學可能會問了,有線程? 那有線程池嗎?必須有!!

在 Rust 中,你可以使用 threadpool crate 來創建一個線程池。以下是一個基本的示例:

use threadpool::ThreadPool;fn main() {let pool = ThreadPool::new(4);for i in 0..10 {let j = i;pool.execute(move || {println!("Hello from thread {}", j);});}
}

這會創建一個包含 4 個線程的線程池。然后我們使用 pool.execute() 方法在線程池中執行 10 個閉包。這些閉包會被線程池的線程執行,并打印出執行線程的索引。

threadpool crate 提供了以下主要功能:

  • ThreadPool::new(size) :創建一個包含 size 個線程的線程池。
  • pool.execute(closure) :在線程池的某個線程中執行提供的閉包。
  • pool.join() :等待線程池中的所有線程結束。
  • ThreadPoolBuilder :可以用來自定義線程池的各種設置,如線程名稱、堆棧大小等。

一個更復雜的例子:

use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;
use threadpool::ThreadPool;fn main() {let pool = ThreadPool::new(4);let (tx, rx) = mpsc::channel();let tx = Arc::new(Mutex::new(tx));for i in 0..10 {let tx = tx.clone();pool.execute(move || {let mut tx = tx.lock().unwrap();tx.send(i).unwrap();});}for _ in 0..10 {let j = rx.recv().unwrap();println!("Got: {}", j);}pool.join();
}

這里我們使用了 mpsc 庫創建一個通道,并使用 Arc<Mutex<T>> 在線程之間共享該通道的發送端。然后我們在 10 個任務中發送數字到通道,并在主線程中接收這些數字。

序列化

在后端開發中,序列化是一個繞不過的話題,前后端交互,后端之間交互都需要對數據做序列化與反序列化。 在 Rust 中,有幾種常用的序列化方式:

  1. Serde:這是 Rust 中最流行的序列化庫。它提供了多種序列化格式的支持,如 JSON、YAML、TOML 等。使用 Serde 可以方便地將 Rust 結構體序列化為這些格式,以及反序列化回 Rust 結構體。

  2. Bincode:這是一個用于在 Rust 中進行二進制序列化的庫。它可以高效地將 Rust 的基本數據結構編碼為二進制,并解碼回原數據結構。

  3. Ron:這是一個用于 Rust 對象表示法 (RON) 的序列化格式和解析器。RON 是一個人類友好的二進制序列化格式,設計用于在 Rust 中存儲和傳輸數據。

  4. CBOR:這是一個實現了約束二進制對象表示法 (CBOR) 的 Rust 庫。CBOR 是一種二進制序列化格式,它比 JSON 更緊湊,也更適用于嵌入式系統。

  5. MessagePack:這是一個實現 MessagePack 二進制序列化格式的 Rust 庫。MessagePack 是一個高效的二進制序列化格式,可以用于在不同語言之間交換數據。

  6. Protobuf:這是 Google 開發的一種數據序列化格式,在 Rust 中可以使用 prostprotobuf 庫來實現。Protobuf 是一種語言無關、平臺無關的可擴展機制,用于序列化結構化數據。

以上就是 Rust 中常用的幾種序列化方式。總的來說,如果你需要一個通用的序列化方式,可以選擇 Serde。如果你需要一個高效緊湊的二進制格式,可以選擇 Bincode、CBOR 或 MessagePack。如果你需要跨語言支持,可以選擇 Protobuf。

這里主要演示下Serde的用法,它提供了一組宏和 trait,用于將 Rust 數據結構轉換為各種格式的序列化表示,并將序列化表示轉換回 Rust 數據結構。

要使用 Serde,首先需要在 Cargo.toml 文件中添加以下依賴項:

[dependencies]
serde = "1.0"
serde_json = "1.0"

接下來,我們將給出一個使用 Serde 進行 JSON 序列化和反序列化的例子:

use serde::{Serialize, Deserialize};
use serde_json::{Result, Value};#[derive(Serialize, Deserialize, Debug)]
struct Person {name: String,age: u8,address: String,
}fn main() -> Result<()> {// 序列化為 JSONlet person = Person {name: "Alice".to_string(),age: 25,address: "123 ABC Street".to_string(),};let serialized = serde_json::to_string(&person)?;println!("Serialized: {}", serialized);// 反序列化為 Rust 結構體let deserialized: Person = serde_json::from_str(&serialized)?;println!("Deserialized: {:?}", deserialized);Ok(())
}

在上面的例子中,我們定義了一個 Person 結構體,并使用 #[derive(Serialize, Deserialize)] 宏為其實現了 Serde 的 SerializeDeserialize trait。這使得我們可以將 Person 結構體序列化為 JSON 字符串,并將 JSON 字符串反序列化為 Person 結構體。

main 函數中,我們首先創建一個 Person 實例,然后使用 serde_json::to_string 方法將其序列化為 JSON 字符串,并打印出來。接著,我們使用 serde_json::from_str 方法將 JSON 字符串反序列化為 Person 結構體,并打印出來。

網絡請求

請求Http接口

在 Rust 中,你可以使用第三方庫來進行 HTTP 請求。最常用的庫之一是 reqwest ,它提供了簡單且易于使用的 API 來發送 HTTP 請求。

首先,你需要在 Cargo.toml 文件中添加 reqwest 依賴項:

[dependencies]
reqwest = "0.11"

接下來,我們將給出一個使用 reqwest 發送 GET 請求的示例:

use reqwest::Error;#[tokio::main]
async fn main() -> Result<(), Error> {let response = reqwest::get("https://api.example.com/users").await?;let body = response.text().await?;println!("Response Body: {}", body);Ok(())
}

在上面的示例中,我們使用 reqwest::get 方法發送一個 GET 請求到 https://api.example.com/users 。然后,我們使用 response.text().await? 來獲取響應的文本內容,并打印出來。

需要注意的是,我們使用了 tokio::main 宏來異步運行請求。因此,你需要在 main 函數之前添加 tokio 作為依賴項,并在 main 函數前面使用 #[tokio::main] 注解。

到目前為止,我們學習了集合、并發、序列化和網絡請求,最后再留一個作業: 請求百度首頁,并解析出所有的http鏈接。 結合本文所學哦

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/38933.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/38933.shtml
英文地址,請注明出處:http://en.pswp.cn/news/38933.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ajax如何理解

什么是ajax ●認識前后端交互 ○就是 前端 與 后端的 一種通訊方式 ○主要使用的技術棧就是 ajax (async javascript and xml) ●ajax 特點 ○使用 ajax 技術網頁應用能夠快速的將新內容呈現在用戶界面 ○并且不需要刷新整個頁面, 也就是能夠讓頁面有 "無…

Java技術整理(5)—— Spring篇

Spring是一個全面的全面的、企業應用開發一站式的解決方案&#xff0c;貫穿表現層、業務層、持久層。但是 Spring 仍然可以和其他的框架無縫整合。 1、Spring的核心組件 &#xff08;1&#xff09;數據層&#xff1a; JDBC、ORM、OXM、JMS、Transations &#xff08;2&#x…

Flutter 中,ListView 中需要放置 ListView 需要怎么處理才高效?

問題及場景 ListView 是 Flutter 開發者第一個學習到的 Widget&#xff0c;因為它可以滑動。一切都會運行得很好&#xff0c;直到 ListView 中的 Item 本身也是一個 ListView。你可能會看到 Flutter 建議你將內部的 ListView 的ShrinkWrap 屬性設置為 True。雖然錯誤消除了&am…

連續兩年增收不增利,比亞迪電子靠新能源汽車業務再次起飛?

在凈利潤連續兩年下挫之后&#xff0c;比亞迪電子&#xff08;00285.HK&#xff09;終于迎來了好消息。 不久前比亞迪電子發布2023年中期盈利預告顯示&#xff0c;上半年凈利潤同比增加115%-146%&#xff08;2022年上半年的凈利潤顯示6.34億元&#xff09;。 這主要受益于大客…

包管理工具 nvm npm nrm yarn cnpm npx pnpm詳解

包管理工具 nvm npm yarn cnpm npx pnpm npm、cnpm、yarn、pnpm、npx、nvm的區別&#xff1a;https://blog.csdn.net/weixin_53791978/article/details/122533843 npm、cnpm、yarn、pnpm、npx、nvm的區別&#xff1a;https://blog.csdn.net/weixin_53791978/article/details/1…

【Freertos基礎入門】2個Freertos的Delay函數

文章目錄 前言一、vTaskDelay與vTaskDelayUntil二、示例代碼總結 前言 本系列基于stm32系列單片機來使用freerots 任務管理是實時操作系統&#xff08;RTOS&#xff09;的核心功能之一&#xff0c;它允許開發者以并發的方式組織和管理多個任務。FreeRTOS 是一個流行的開源RTO…

嵌入式開發中常用且雜散的命令

1、mount命令 # 掛載linux系統 mkdir /tmp/share mount -t nfs 10.77.66.88:/share/ /tmp/share -o nolock,tcp cd /tmp/share# 掛載Windows系統 mkdir /tmp/windows mount -t nfs 10.66.77.88:/c/public /tmp/windows -o nolock,tcp cd /tmp/windows# 掛載vfat格式的U盤 mkdi…

強訓第32

選擇 D B A A 發送TCP意思應該是已經建立了連接&#xff0c;會超時重傳。在未建立連接的時候&#xff0c;會放棄該鏈接 C A 80端口是http A 交換機攻擊主要有五種&#xff1a;VLAN跳躍攻擊 生成樹攻擊 MAC表洪水攻擊 ARP攻擊 VTP攻擊 B A 2^(32-26)2^(32-27)2^(32-27)128 減去…

基于Java+SpringBoot+Vue+echarts健身房管理系統設計和實現

博主介紹&#xff1a;?全網粉絲30W,csdn特邀作者、博客專家、CSDN新星計劃導師、Java領域優質創作者,博客之星、掘金/華為云/阿里云/InfoQ等平臺優質作者、專注于Java技術領域和畢業項目實戰? &#x1f345;文末獲取源碼聯系&#x1f345; &#x1f447;&#x1f3fb; 精彩專…

maven Jar包反向install到本地倉庫

maven Jar包反向install到本地倉庫 需求實現 需求 項目打包時報錯&#xff0c;缺少一個jar包。 但是在maven倉庫都找不到此jar包&#xff0c;其他人提供了這個jar包。 需要把這個jar包install到本地倉庫&#xff0c;使項目能正常打包運行。 實現 使用git bash命令執行以下腳…

16.3.4 【Linux】系統資源的觀察

free &#xff1a;觀察內存使用情況 系統當中有 2848MB 左右的實體內存&#xff0c;我的 swap 有 1GB 左右&#xff0c; 那我使用free -m 以 MBytes 來顯示時&#xff0c;就會出現上面的信息。Mem 那一行顯示的是實體內存的量&#xff0c;Swap 則是內存交換空間的量。 total 是…

C++多態

文章目錄 &#x1f435;1. 什么是多態&#x1f436;2. 構成多態的條件&#x1f429;2.1 虛函數&#x1f429;2.2 虛函數的重寫&#x1f429;2.3 final 和 override關鍵字&#x1f429;2.4 重載、重寫、重定義對比 &#x1f431;3. 虛函數表&#x1f42f;4. 多態的原理&#x1f…

神經網絡基礎-神經網絡補充概念-17-計算神經網絡的輸出

計算神經網絡的輸出通常涉及前向傳播&#xff08;Forward Propagation&#xff09;的過程&#xff0c;其中輸入數據通過網絡的層級結構&#xff0c;逐步被傳遞并變換&#xff0c;最終生成預測結果。下面我將為你展示一個簡單的神經網絡前向傳播的示例。 假設我們有一個具有以下…

【變形金剛01】attention和transformer所有信息

圖1.來源&#xff1a;Arseny Togulev在Unsplash上的照片 一、說明 這是一篇 長文 &#xff0c;幾乎討論了人們需要了解的有關注意力機制的所有信息&#xff0c;包括自我注意、查詢、鍵、值、多頭注意力、屏蔽多頭注意力和轉換器&#xff0c;包括有關 BERT 和 GPT 的一些細節。因…

OpenCV圖像處理——輪廓檢測

目錄 圖像的輪廓查找輪廓繪制輪廓 輪廓的特征輪廓面積輪廓周長輪廓近似凸包邊界矩形最小外接圓橢圓擬合直線擬合 圖像的矩特征矩的概念圖像中的矩特征 圖像的輪廓 查找輪廓 binary,contours,hierarchycv.findContours(img,mode,method)繪制輪廓 cv.drawContours(img,coutours…

WSL2安裝Ubuntu,配置機器學習環境

文章目錄 1.WSL2安裝Ubuntu&#xff0c;更改安裝位置&#xff0c;作為開發環境供vscode和pycharm使用&#xff1a;2.更換國內源&#xff1a;3.安裝圖形界面&#xff1a;4.安裝cudacudnntorch5.安裝opencv6.調用攝像頭7.使用yolov8測試 WSL全稱Windows Subsystem for Linux&…

印度貨代專線【我國到印度專線有哪些方式】

隨著全球貿易的不斷發展&#xff0c;我國與印度之間的貿易往來也日益頻繁。作為兩個人口最多的國家之一&#xff0c;中國和印度之間的貨物運輸需求不斷增長。為了滿足這一需求&#xff0c;印度貨代專線應運而生&#xff0c;為進出口商提供高效、可靠的貨物運輸服務。本文將探索…

939. 最小面積矩形;2166. 設計位集;2400. 恰好移動 k 步到達某一位置的方法數目

939. 最小面積矩形 核心思想&#xff1a;枚舉矩形的右邊那條邊的兩個點&#xff0c;并用一個哈希表存儲相同縱坐標的最近出現的列的列數,不斷更新最近出現的左邊那條邊。 2166. 設計位集 核心思想&#xff1a;這題主要是時間復雜度的優化&#xff0c;用一個flag來標記當前翻轉…

CSS自學框架之表單

首先我們看一下表單樣式&#xff0c;下面共有5張截圖 一、CSS代碼 /*表單*/fieldset{border: none;margin-bottom: 2em;}fieldset > *{ margin-bottom: 1em }fieldset:last-child{ margin-bottom: 0 }fieldset legend{ margin: 0 0 1em }/* legend標簽是CSS中用于定義…

IOS開發-XCode14介紹與入門

IOS開發-XCode14介紹與入門 1. XCODE14的小吐槽2. XCODE的功能bar一覽3. XCODE項目配置一覽4. XCODE更改DEBUG/RELEASE模式5. XCODE單元測試 1. XCODE14的小吐槽 iOS開發工具一直有個毛病&#xff0c;就是新版本的開發工具的總會有一些奇奇怪怪的bug。比如在我的Mac-Pro&#…