簡體   English   中英

ArrayList與HashSet的性能

[英]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進行基准測試之前,對有缺陷的微基准測試進行剖析

簡短的解釋是,你要衡量有總持續時間是非常非常太短,和基准測試結果將通過微小的OS和CPU細節被淹沒,並通過一個事實,即Java虛擬機仍忙於編譯字節碼在開始運行時加工代碼。

同時,這是一個有點瘋狂的時候,他們有兩個不同的目的來比較ArrayList和HashList性能,但所有其他條件相同,ArrayList中的實現是顯著更簡單 ,所以你的假設是無疑是正確的; 它會更快。

這里的真正問題是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM