[英]Performance of ArrayList vs HashSet
我知道當我們需要存儲重復項時,我們更喜歡使用ArrayList
不是HashSet
,而HashSet
使用hashCode()
函數來計算其數組中每個元素的索引。
因此,這意味着如果我們想要存儲單個元素,那么ArrayList
應該比HashSet
花費更少的時間。 如果我在任何地方都錯了,請糾正我。
但是當我通過代碼檢查性能時,我會得到不同的行為。
情況1:
import java.util.*;
class HashsetVSArraylist
{
public static void main(String args[])
{
ArrayList<Integer> a1=new ArrayList<Integer>();
long nanos = System.nanoTime();
a1.add(1);
System.out.println("ArrayList Time:"+(System.nanoTime()-nanos)+"ns");
HashSet<Integer> h1=new HashSet<Integer>();
nanos = System.nanoTime();
h1.add(2);
System.out.println("HashSet Insertion Time:"+(System.nanoTime()-nanos)+"ns");
}
}
Output:
ArrayList Time:495087ns
HashSet Insertion Time:21757ns
案例2:
import java.util.*;
class HashsetVSArraylist
{
public static void main(String args[])
{
HashSet<Integer> h1=new HashSet<Integer>();
long nanos = System.nanoTime();
h1.add(2);
System.out.println("HashSet Insertion Time:"+(System.nanoTime()-nanos)+"ns");
ArrayList<Integer> a1=new ArrayList<Integer>();
nanos = System.nanoTime();
a1.add(1);
System.out.println("ArrayList Time:"+(System.nanoTime()-nanos)+"ns");
}
}
Output:
HashSet Insertion Time:582527ns
ArrayList Time:21758ns
現在,我假設HashSet
應該花更多時間插入單個元素。 但是,在這兩種情況下,行為都是不同的......代碼中排在第二位的數據結構花費的時間更少。 此外,當插入的元素數量超過1000時,行為也會更改。
請解釋一下發生了什么。
這里的真正問題是Java在將整數原語轉換為Integer對象時所做的自動裝箱。
當你調用a1.add(1)時,這實際上是調用a1.add(Integer.valueOf(1))
第一次引用Integer類的靜態valueOf方法時,導致在Integer類中執行靜態初始化程序,這會創建數百個靜態對象,並且在系統上大約需要500ms。
即便如此,在幕后還會發生許多干擾此測試的其他事情,例如其他靜態初始化器,動態內存分配,系統資源分配以及無數其他。
如果你可以設計一個消除或最小化這些變量的測試,那么你會發現從長遠來看,ArrayList的添加總是比HashSet快,但對於任何給定的插入都沒有。 幸運的是,我們永遠不應該關心單次插入的速度。
例如,想象一下嘗試向ArrayList添加值的幾乎最壞的情況,但是ArrayList是它的最大分配大小。 ArrayList嘗試分配更多空間,但系統已達到當前內存分配上限,因此需要等待VM為系統分配更多內存。 同時垃圾收集器開始了。 在這種情況下,通常可能需要<1ms的插入可能需要多秒才能執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.