HashMap與Vec的性能注意,因?yàn)檫@里主要用Rust來論述這個問題,如果對應(yīng)到Python,就是dict與list,效果是一樣的。 看到這個問題,可能很多同學(xué)都會說,這個還要你說?HashMap的是基于kv結(jié)構(gòu)的,查詢復(fù)雜度是O(1),而Vec的查詢復(fù)雜度是O(n),是個人都知道HashMap的復(fù)雜度高啊。看下面這個場景: let size = 1000000; let mut rng = rand::thread_rng(); let mut vec_info:Vec<(String,i32)> = Vec::with_capacity(size); let mut hashmap_info:HashMap<usize,(String,i32)> = HashMap::with_capacity(size);
for i in 0..size{ //生成一個abc.abcde這樣格式的模擬名字 let name = format!("{}.{}",generate_random_string(rng.to_owned(),3),generate_random_string(rng.to_owned(),5)); //生成一個隨機(jī)年齡 let age = rng.gen_range(22..=60); vec_info.push((name.to_owned(), age)); hashmap_info.insert(i, (name.to_owned(), age)); }
我分別定義了一個hashmap和一個vec,默認(rèn)容量都是100萬小貼士:在Rust、CPP一類編譯型語言中,預(yù)先對集合進(jìn)行內(nèi)存分配,可以有效的提高內(nèi)存使用率和程序效率。 然后定義了一個數(shù)據(jù)結(jié)構(gòu),分別存儲了模擬的人員信息,例如一個姓名一個年齡,并且把這個數(shù)據(jù)存入到我們的hashmap和vec中,存進(jìn)去的信息類似下面這種:vec:vec里面直接按照數(shù)值序列進(jìn)行存儲,我們可以把序列號認(rèn)為的ID[ ("iYP.NHqtJ", 24), ("Tr1.YITPi", 34), ("cMx.gkNIA", 58), …… ]
hashmap:hashmap里面用kv模式存儲,序列號(ID)就是他們的key{ 0: ("iYP.NHqtJ", 24), 1: ("Tr1.YITPi", 34), 2: ("cMx.gkNIA", 58), …… }
然后隨機(jī)讀取其中的1000個信息: //隨機(jī)訪問vec中的1000個記錄 let start = Utc::now(); for i in 0..1000{ let idx = rng.gen_range(0..size); println!("name= {} age = {}",vec_info[idx].0,vec_info[idx].1); } let end = Utc::now(); let vec_o = end.timestamp_subsec_micros()-start.timestamp_subsec_micros();
//隨機(jī)訪問hashmap中的1000個記錄 let start = Utc::now(); let start = Utc::now(); for i in 0..1000{ let idx = rng.gen_range(0..size); println!("{:?}",hashmap_info[&idx]); } let end = Utc::now();
在debug模式下,執(zhí)行結(jié)果如下: ?。?! vec的下標(biāo)隨機(jī)訪問,100萬里面獲取其中的1000條,比hashmap通過key進(jìn)行隨機(jī)訪問,快了20%效率。實(shí)際上,我們回憶一下數(shù)據(jù)結(jié)構(gòu),大家就能想起來,原文是這樣說的:?HashMap?是一種基于哈希表的數(shù)據(jù)結(jié)構(gòu),用于存儲鍵值對(key-value pairs),其中每個鍵都是唯一的。HashMap提供了快速查找、插入和刪除操作,平均時間復(fù)雜度為O(1)。 注意,理論上,hashmap是O(1)的,但是在具體實(shí)現(xiàn)的時候,不同的語言設(shè)計(jì)會出現(xiàn)一定的開銷,而vec的下標(biāo)訪問,幾乎是無開銷的直接訪問內(nèi)存,所以性能高了差不多20%。說到這里,如果有同學(xué)要Java做同類的測試,發(fā)現(xiàn)hashmap的性能可能更慘,是因?yàn)镴ava的HashMap實(shí)現(xiàn)用的是紅黑樹來實(shí)現(xiàn)的,而紅黑樹的查詢復(fù)雜度是O(logn)……我們直接遍歷整個集合,并且取出來每個數(shù)值,這里就不進(jìn)行print了,因?yàn)閜rint的開銷還是挺大的,會卡半天,結(jié)果如下:vec進(jìn)行全集合遍歷的性能,幾乎是比hashmap遍歷快了230%…… 結(jié)論:如果是通過下標(biāo)直接訪問,或者遇上需要遍歷全部信息的情況下,vec的性能要比hashmap更好。那么如果是增加刪除修改呢?誰的性能更好?請聽下回分解。
|