如何選擇集合

2021-05-04 23:26:29 字數 3826 閱讀 8693

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

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

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

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

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

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

1.arraylist:

陣列實現的保持進入順序的集合。

查詢元素操作

(提供索引位置

):計算元素記憶體指標位置,一步便可跳到。

增加元素操作:查詢到增加位置的元素,後面的元素挨個向後移乙個位置,儲存元素的

時間可以忽略不計

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

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

2.linkedlist:

鍊錶實現的保持進如順序的集合。

查詢元素操作

(提供索引

):從根節點遍歷,不能跳越,直到索引要求的位置。

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

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

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

3.hashset/hashmap:

無序的hash

演算法來索引的集合

查詢元素操作:

hashcode

經過hash

演算法直接指向記憶體位址,而後呼叫指向的資料的

equals()

,如果不等,繼續

hash

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

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

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

4.treeset/treemap:

根據指定值排序的集合,低層是鍊錶

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

linkedlist

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

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

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

效能分析表:集合/

操作a增b

刪c查d

改順序性

arraylistc+④

=a①=c進入順序

linkedlistc+①

=a④=c進入順序

hashset/hashmapc+②

=a②=c無順序

treeset/treemapc+③

=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 行為時請考慮使...