如何選擇集合

2021-06-07 02:17:18 字數 3365 閱讀 6698

在程式設計的過程中,選擇何種集合至關重要,下面由我來總結下選擇集合的方法

選擇集合所考慮的關鍵問題在於:效率代價與空間代價的平衡問題。

效率代價是指執行的效率,簡單的說如果乙個資源沒有把索引記錄下來,那麼要找到他你就需要執行程式,那麼你的代價在於系統花錢了時間。

空間代價是指存放的空間消耗記憶體的代價,如上邊說到的如果把索引記錄下來很方便就能找到要找的資源,也就是用空間代價換取執行時間的縮短。這就像**本除了記號碼還要記人名,總不能乙個個打**去問誰是張三李四的吧。

我想說的是,現在的儲存器越來越便宜,空間可以說不是難題,空間代價不是優先考慮的問題。

下面我們來分析下各種常用的集合資料型別

1.       arraylist:陣列實現的保持進入順序的集合。

查詢元素操作(提供索引位置):計算元素記憶體指標位置,一步便可跳到。

增加元素操作:查詢到增加位置的元素,後面的元素挨個向後移乙個位置,儲存元素的      時間可以忽略不計

刪除元素操作:查詢到增加位置的元素,後面的元素挨個向前移乙個位置,清空元素的時間可以忽略不計

修改元素操作:與查詢元素操作效率相同

2.       linkedlist:鍊錶實現的保持進如順序的集合。

查詢元素操作(提供索引):從根節點遍歷,不能跳越,直到索引要求的位置。

增加元素操作:查詢到增加位置的元素,接上鏈的時間忽略不計

刪除元素操作:查詢到增加位置的元素,拆下鏈的時間忽略不計

修改元素操作:與查詢元素操作效率相同

3.       hashset/hashmap:無序的hash演算法來索引的集合

查詢元素操作:hashcode經過hash演算法直接指向記憶體位址,而後呼叫指向的資料的equals(),如果不等,繼續hash演算法。

增加元素操作:查詢到增加位置的元素,儲存的時間忽略不計

刪除元素操作:查詢到增加位置的元素,刪除的時間忽略不計

修改元素操作:與查詢元素操作效率相同

4.       treeset/treemap:根據指定值排序的集合,低層是鍊錶

查詢元素操作:紅黑二分查詢樹演算法,鍊錶遍歷跳過部分節點,效率大於linkedlist

增加元素操作:查詢到增加位置的元素,接上鏈的時間忽略不計

刪除元素操作:查詢到增加位置的元素,拆下鏈的時間忽略不計

修改元素操作:與查詢元素操作效率相同

效能分析表:

集合/操作

a增b刪

c查d改

順序性arraylist

c+④=a

=c進入順序

linkedlist

c+①=a

=c進入順序

hashset/hashmap

c+②=a

=c無順序

treeset/treemap

c+③=a

=c指定順序

注釋:=a表示效率上等於其a操作,也就是增操作,=c也同理;c+①表示查詢效率要加入計算。

從上面中最核心的問題是arraylist增刪操作與linkedlist查詢操作代價比較

案例1:arraylist與linkedlist的add/remove操作的比較

分析1:低效率arraylist.add/remaove操作的原因在於增刪操作可能會引起元素的交換,而linkedlist的增刪只需要接鏈頭和鏈尾。

結果資料1:arraylist的100萬次的交換消耗了3mm

案例2:arraylist與linkedlist的get操作的比較

分析2:linkedlist的查詢操作效率低的原因是必須遍歷過程中的每個節點,但是遍歷一次僅相當於getter方法呼叫消耗非常小。

結果資料2:linkedlist的166萬次的遍歷都消耗都不到1mm

結論:通過以上案例測試得知,遍歷元素與交換元素的效率差至少是十萬級的。所以我們幾乎可以忽略linkedlist查詢的效率,而hashset/hashmap,treeset/treemap效率比linkedlist還要高,也可以忽略其查詢效率。

由此,應修改效能分析表如下:

效能分析表:

集合/操作

a增b刪

c查d改

順序性arraylist

=a=c

進入順序

linkedlist

=a=c

進入順序

hashset/hashmap

=a=c

無順序treeset/treemap

=a=c

指定順序

總結:1:如果元素沒有順序要求,有優的選擇是hashset/hashmap,其增刪查詢的效率都很高。

2:如果元素有順序要求,對於arraylist、linkedlist和treeset/treemap都可以實現,只是arraylist、linkedlist需要控制進入順序,而treeset/treemap需要值記錄順序。如果記錄順序的值很方便提供,優先選擇treeset/treemap。

3:如上述有順序要求,而記錄順序的值不方便提供的情況,如stack,如果提供入棧時間比較冗餘。這個時候則考慮集合會不會出現元素順序改動的增刪操作,如果會則選擇linkedlist。如案例1,2中的結論arraylist的單位次交換耗時至少是linkedlist遍歷乙個節點的50萬倍以上。

4:如上述情況有順序要求,並且不希望提供值來排序,而且集合的順序基本不會發生改變,選擇arraylist。

選擇set還是map?

誤點1:map比set資料多出乙個維度,那麼就可以利用多出的部分影響順序或多出快捷收索功能。

正解1:原則是乙個集合物件只能提供乙個索引。

對於map其有效的索引則是key(實際上是key的equals和hashcode),而value是不能主導乙個條目的,如map的remove就不能通過value來刪除,map也不支援value找到key的方法(如果iterator遍歷找到key那就不能稱之為索引到)。

還是乙個真理乙個集合僅提供乙個索引,set和map的區別只在於,索引是否唯一且資料本身就可以提供。只有滿足這兩個條件才可以使用set。因為set有賴於元素本身的equals/hashcode和comparto方法,而這些方法只能由屬性運算得出結果,所以屬性要求有能力提供出索引。而set的元素型別一旦被確定,也就說用兩個set為同乙個資料加索引,其索引規則相同,這是因為元素類獨有乙份equals/hashcode和comparto方法的實現。

如果索引需要多個或資料物件的屬性沒有能力給出此索引,那麼我們會選擇map。map的key可以是我們定製的物件型別,也就是提供不同的equals/hashcode和comparto的方法實現,而不像set只能呼叫到資料本身的一種實現。選擇不同的key型別就會得到不同的方法實現,建立不同的索引,從而多個map能實現多個索引。

如果希望同乙個資料可能會被多種值檢索到,那麼就為他們各自建立乙個map,多個map多個索引方式。map總是能實現索引,而set只能提供自身的一種索引,set是map的特例情況。

如何選擇集合

在程式設計的過程中,選擇何種集合至關重要,下面由我來總結下選擇集合的方法 選擇集合所考慮的關鍵問題在於 效率代價與空間代價的平衡問題。效率代價是指執行的效率,簡單的說如果乙個資源沒有把索引記錄下來,那麼要找到他你就需要執行程式,那麼你的代價在於系統花錢了時間。空間代價是指存放的空間消耗記憶體的代價,...

Collection集合總結及如何選擇集合

collection集合總結 collection list 有序,可充復 arraylsit 底層資料結構是陣列,查詢快,增刪慢 執行緒不安全 效率高 vector 底層資料是陣列,查詢快增刪慢 執行緒安全,效率低 linledlsit 底層資料是鍊錶,查詢慢,增刪快 執行緒不安全 效率高 set...

C 集合類選擇

一定要謹慎選擇 system.collections 類。選用錯誤的型別可能限制您使用集合。考慮以下問題 您是否需要乙個序列列表,其中的元素通常在檢索其值後被放棄?如果需要,那麼在需要先進先出 fifo 行為時請考慮使用 queue 類或 queue 泛型類。在需要後進先出 lifo 行為時請考慮使...