2016-10-07 85 views
1

我在處理對象時面臨困惑。我搜索谷歌,但無法找到真正的單詞來搜索。問題是:使用變量而不是長語句?

我正在使用包含其他對象的對象。例如:

public void mapObjects(A a, B b) { 
    a.setWeight(BigDecimal.valueOf(b.getWeight)); 
    //Now my doubt lies here 
    if (a.getCharges.getDiscounts.getDiscountList != null) { 
     for(int i = 0; i < a.getCharges.getDiscounts.getDiscountList.size(); i++){ 
      b.getList().get(0).setDiscountValue(a.getCharges.getDiscounts.getDiscountList.get(i).getValue()); 
      b.getList().get(0).setDiscountName(a.getCharges.getDiscounts.getDiscountList.get(i).getValue); 
     } 
    } 

} 

上面的代碼只是一個例子。我工作的項目使用類似的編碼風格。使用a.getCharges.getDiscounts.getDiscountList()類型的代碼總是讓我感到困惑。因爲我一次又一次地調用同樣的聲明。

當我問一位高級職員爲什麼我們不把這個聲明保存到一個簡單的列表<>變量中。他告訴我,它會使用額外的引用,這會增加開銷。可以使用一個變量,而不是一次又一次地調用getters?

+10

你的「老人」完全是瘋子。 –

+0

這讓我想吐...... –

+0

這就是問題所在。現在我們的代碼完全是一堆冗長的陳述。我們無法提供幫助,因爲它需要改變。 – Anant666

回答

2

由於Java交換引用不是實際的對象,所以如果你使用一個局部變量,它只會在棧幀中添加一個引用變量條目。

  • 這種記憶會非常少,幾乎可以忽略不計
  • 一旦方法完成,因爲這將是本地的方法

儘管該內存將被釋放,你可以得到顯著的性能如果您使用局部變量則會獲益。您在循環內多次提取相同的信息。

  1. a.getCharges.getDiscounts.getDiscountList.size()被稱爲多次。它應該是一個局部變量。
  2. b.getList().get(0)被多次調用。它應該是一個局部變量。
  3. a.getCharges.getDiscounts.getDiscountList被稱爲多次。它應該是一個局部變量。

將這些更改爲局部變量會導致良好的性能收益,因爲可以節省不必要的方法調用。

1

將你的前輩指向this。如果它適用於Android上的有限資源,那麼我認爲在for循環中使用的所有東西都存儲在本地變量中的技術實際上對於任何地方的性能都是有益的。

在下面的摘錄中,請注意,我們甚至沒有談到通過調用(虛擬)list.size()方法引入的開銷,只將array.length作爲局部變量存儲會在性能上產生顯着差異。

public void zero() { 
    int sum = 0; 
    for (int i = 0; i < mArray.length; ++i) { 
     sum += mArray[i].mSplat; 
    } 
} 

public void one() { 
    int sum = 0; 
    Foo[] localArray = mArray; 
    int len = localArray.length; 

    for (int i = 0; i < len; ++i) { 
     sum += localArray[i].mSplat; 
    } 
} 

public void two() { 
    int sum = 0; 
    for (Foo a : mArray) { 
     sum += a.mSplat; 
    } 
} 

零()是最慢的,因爲JIT還不能優化掉得到數組長度一次通過循環每次迭代的成本。

one()更快。它將所有東西都拉到局部變量中,避免查找。只有陣列長度才能提供性能優勢。

對於沒有JIT的設備,two()是最快的,對於帶有JIT的設備而言,它與one()無法區分。它使用Java編程語言1.5版中引入的增強for循環語法。

0

只需使discountList字段永不爲空 - 即初始化爲空列表並對其進行迭代。例如:

for (Discount discount : a.getCharges().getDiscounts().getDiscountList()) { 
    b.getList().get(0).setDiscountValue(discount.getValue()); 
    b.getList().get(0).setDiscountName(discount.getName()); 
} 

您的「高級」可能需要做一些研究。這樣做的「性能影響」是每個對象幾個字節,每個訪問幾微秒。如果他真的關於內存的問題,用一個幾乎沒有內存佔用的LinkedList進行初始化。

+0

沒有得到最後一行。 –

+1

@Amber大多數人不用思考就使用ArrayList。 ArrayLists使用大小爲16的備份數組進行初始化,因此將燒錄17個存儲器位置。但LinkedLists在初始化時不會爲元素分配任何內存,因此如果它們通常爲空(或幾乎爲空),則它們使用的內存少於ArrayLists(即使它們在增長時每個元素使用更多的內存)。 – Bohemian

0

在Java中,指向對象實例O的變量V只是一個指向存儲對象數據的內存位置的數值。

當我們分配V另一個變量V1所發生的一切是V1現在指向哪裏的O數據存儲在相同的內存位置。這意味着新存儲器在執行簡單分配時未分配,與C++代碼不同,其中=運算符可被重載以執行深度複製,在這種情況下實際分配了新內存。下面

一個例子說明考慮像下面

class Foo { 

    private List<String> barList = new ArrayList<>(); 

    //class methods... 

    //getter for the list 
    List<String> getBarList() { 
     return this.barList; 
    } 
} 

public static void main(String[] args) { 

    Foo f = new Foo() 
    //the below lien will print 0 since there is no bar string added 
    System.out.println("Bar list size: " + f.getBarList().size()); 

    // add a bar string. Observe here that I am simply getting the list 
    // and adding - similar to how your code is currently structured 
    f.getBarList().add("SomeString"); 
    //now get a reference to the list and store it in a variable. 
    // Below anotherList only points to the same memory location 
    // where the original bar list is present. No new memory is allocated. 
    List<String> anotherList = f.getBarList(); 
    //print the content of bar list and another list. Both will be same 
    for(String s : f.getBarList()) { 
    System.out.println(s); 
    } 
    for(String s: anotherList) { 
    System.out.println(s); 
    } 

    //add a new bar string using the reference variable 
    anotherList.add("Another string"); 
    //print the content of bar list and another list. Both will be same. If anotherList had separate memory allocated to it then the new string added would be only seen when we print the content of anotherList and not when we print the content of f.getBarList(). This proves that references are only some numeric addresses that point to locations of the object on heap. 
    for(String s : f.getBarList()) { 
    System.out.println(s); 
    } 
    for(String s: anotherList) { 
    System.out.println(s); 
    } 

} 

希望這有助於類。

+0

請添加一個解釋如何回答這個問題,因爲它代表着它,它看起來像一個零信息介紹的代碼刪除。 –

+0

@MarkRotteveel感謝您的反饋 - 我已經通過一些初步介紹更新了答案 –