2016-10-07 26 views
1

オブジェクトの操作中に混乱に直面しています。私はGoogleを検索しましたが、検索する実際の単語を見つけることができませんでした。問題は次のとおりです。long文の代わりに変数を使用しますか?

他のオブジェクトで構成されているオブジェクトを使用しています。例:

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()種類の使用は常に私をバグします。なぜなら私は何度も同じ声明を呼んでいるからです。

私はシニアに尋ねたときに、この文を単純なList <>変数に保存しないでください。彼はオーバーヘッドを増やす余分な参照を使用すると私に言った。変数を使用すると、ゲッターを何度も何度も呼び出すよりもオーバーヘッドになる可能性がありますか?

+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をローカル変数として保存するだけで、パフォーマンスに著しい違いが生じます。 JITはまだループの反復ごとに一度配列の長さを得るためのコストを離れて最適化することができないため

    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; 
        } 
    } 
    

    ゼロ()は、最も遅いです。

    one()が高速です。ルックアップを避けて、すべてをローカル変数に引き出します。配列の長さだけがパフォーマンス上の利点を提供します。

    two()はJITのないデバイスでは最も高速で、JITがあるデバイスでは()と区別がつきません。これは、Javaプログラミング言語のバージョン1.5で導入された拡張forループ構文を使用します。

    0

    discountListフィールドがnullにならないようにする、つまり空のリストに初期化して、それを反復処理します。次のようなものがあります。

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

    あなたの「シニア」はいくつかの調査を行う必要があります。これを実行する "パフォーマンスの影響"は、オブジェクトあたり数バイト、アクセスあたり数マイクロ秒です。彼が本当にメモリを使い果たしているなら、LinkedListで初期化してください。LinkedListはメモリ占有量がほとんどありません。

    +0

    最後の行が見つかりませんでした。 –

    +1

    @Amberほとんどの人は、考えずにArrayListsを使用しています。 ArrayListsはサイズ16のバッキング配列で初期化されるため、17のメモリ位置が書き込まれます。しかし、LinkedListsは、初期化時に要素のためのメモリを割り当てないので、通常は空(またはほとんど空)の場合、ArrayListsより少ないメモリを使用します。 – Bohemian

    0

    Javaでは、オブジェクトインスタンスOを指す変数Vは、単にオブジェクトのデータが格納されているメモリ位置を指す数値です。

    我々はV1が今Oのデータが格納されている同一のメモリ位置を指し示すことである起こる別の変数V1全てにVを割り当てる場合。つまり、=演算子にディープコピーを実行して新しいメモリが実際に割り当てられる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フィードバックいただきありがとうございます - 私はいくつかの予備的な紹介で答えを更新しました –

    関連する問題