2015-11-06 64 views
0

我知道這很簡單,但我無法找到任何問題。檢查java上的列表是否爲空會影響性能?

當我檢查一個列表是否爲空然後迭代它時,它會如何影響性能?

我有以下代碼,我不知道第二次調用getContainers()是否再次執行該方法,或者編譯器正在保存列表,因此不必再次運行getContainers()。

if (getContainers() != null) 
{ 
    for (Container container : getContainers()) 
{... 

如果這不是真的我正在考慮做類似下面的代碼,但它似乎天真。

List<Container> listC = getContainers(); 
if (listC != null) 
{ 
    for (Container container : listC) 
{... 
+1

第二種方法調用getContainers一次,所以它的性能更好 –

+1

添加簡單的System.out.println()到getContainers(),你會看到結果=)對我來說第二個變體更好。 – Lugaru

+0

檢查一個對象是否爲null幾乎沒有影響性能。第二種方法會有更好的性能,因爲它不會重複'getContainers()'方法中完成的操作;換句話說,它得到(或者在'null'結果的情況下沒有得到)列表***一次***;但這與'null'檢查本身的性能影響無關。 – XenoRo

回答

0

這個問題令人混淆。事實是,您需要檢查getContainers()是否在某個時候返回null,除非您允許NullPointerException,在這種情況下,您決定不抓住機會。在這兩個示例中,您都檢查爲空,所以此操作完全相同。

你真正感興趣的是,寫兩次getContainers()是否會影響性能。如果你明白這個方法除了返回一個存儲在(可能是私有的)本地類中的對象之外沒有任何其他的作用,那麼你不應該擔心任何性能,因爲它會不明顯。如果它確實做了更復雜的事情,但可以通過其他方法緩存,那麼您應該查看其他方法。調用它兩次可能不是這個方法的錯誤。如果有疑問,第二個例子保證它只被調用一次,代價是爲它聲明一個變量。

同樣重要的是要注意的是,在增強的for循環,

for (Container container : getContainers()) 

的getContainers()只調用一次,並循環不是在每次迭代。它在內部檢索列表並從中獲取一個迭代器,該迭代器爲每次迭代的容器賦值。唯一的問題是它不檢查NPE。

4

第2版是非常有兩個原因:

  • 不那麼重要:你提到的,如果它不是由編譯器自動
  • 更重要的是優化爲性能優勢:如果在多線程環境下運行時,對getContainers()的兩次調用可能不會產生相同的結果:第一個調用可能不爲空,但第二個調用可能不是。
+0

請注意,第二點中提到的可能性將禁止第一點中提到的編譯器進行優化。 – skyking

+0

@skyking:不一定。我對Java編譯器知之甚少,但我確實知道其他編譯器根據多線程的缺失或存在情況進行不同的優化。我想到的是將來使用爲單線程環境創建的代碼可能很難找到錯誤。 –

+0

好的,但Java編譯器是否真的可以確定在編譯時?我的意思是,如果它將它編譯爲'.class'文件,然後'.class'文件與其他一些實際啓動新線程的'.class'文件一起使用,那麼如果第一個文件假定第二個文件應該不創建線程。 – skyking

2

它很可能會調用getContainers函數兩次。除非知道它不能被覆蓋,因此可以得出結論,它沒有副作用並返回相同的值。

因此,這是合理的做你的第二個例子顯示。但是請注意,它只會被調用兩次,通常不會有足夠的理由來嘗試這種優化。

在嘗試優化之前,應該實際測量代碼在優化之前和之後需要多少時間。之前,因爲它會告訴你是否需要優化,以及之後爲了看到你已經實際優化了(我見過一些「優化」增加了執行時間)。

+1

由於你的答案是關於微優化的,所以你可能需要包含[this](http://stackoverflow.com/questions/1923795/java-method-invocation-vs-using-a-variable)鏈接:) – sam