Java性能の最適化

21075 ワード

一、循環条件に複雑な表現を使わないようにします。コンパイル最適化をしない場合、循環条件は繰り返し計算されます。複雑な表現を使わずに循環条件値を変えたら、プログラムがより速く実行されます。例:
import java.util.vector;

class Demo {

    void method (vector vector) {

        for (int i = 0; i < vector.size (); i++) ;
    }

}
  :

class Demo_fixed {

    void method (vector vector) {

        int size = vector.size ()

        for (int i = 0; i < size; i++); 

    }

}
二、「vectors」と「hashtables」のために初期サイズjvmをvectorの拡充サイズとして定義するときは、もっと大きな配列を新たに作成し、元の配列の内容をコピーして、最後に元の配列を再回収する必要があります。vectorの容量の拡大は時間がかかります。通常、デフォルトの10要素のサイズは足りません。必要なサイズを正確に見積もるのが一番いいです。例:
import java.util.vector;

public class dic {

public void addobjects (object[] o) {

    // if length > 10, vector needs to expand

    for (int i = 0; i< o.length;i++) {

        v.add(o); 
    }
}

    public vector v = new vector(); // no initialcapacity.
}
訂正:初期サイズを自分で設定します。
public vector v = new vector(20);

public hashtable hash = new hashtable(10);
三、finallyブロックにおいてstreamプログラムをクローズする際に使用されるリソースは、資源の漏洩を避けるためにリリースされるべきである。これはfinallyの中でやったほうがいいです。プログラムの実行結果にかかわらず、finallyブロックは常にリソースの正確なクローズを確保するために実行されます。例:
import java.io.*;

public class cs {

public static void main (string args[]) {

    cs cs = new cs ();
    cs.method ();
}

public void method () {

try {
    fileinputstream fis = new fileinputstream ("cs.java");
    int count = 0;
    while (fis.read () != -1)

    count++;

    system.out.println (count);

    fis.close ();

} catch (filenotfoundexception e1) {} 
catch (ioexception e2) {}
}
}
訂正:最後のcatchの後にfinallyブロックを追加して、資源の解放を行います。
四、'system.arraycopy()を使用して、コピー配列'system.arraycopy()を循環するよりも配列をコピーするほうが早いです。例:
public class irb

{
    void method () {
        int[] array1 = new int [100];
        for (int i = 0; i < array1.length; i++) {
            array1 [i] = i;
        }

        int[] array2 = new int [100];
        for (int i = 0; i < array2.length; i++) {
            array2 [i] = array1 [i]; // violation
        }
    }
}
訂正:
public class irb

{
    void method () {
        int[] array1 = new int [100];
        for (int i = 0; i < array1.length; i++) {
            array1 [i] = i;
        }
        int[] array2 = new int [100];
        system.arraycopy(array1, 0, array2, 0, 100);
    }
}
五、アクセスインスタンス内の変数のgetter/setter方法を「final」の簡単なgetter/setter方法をfinalに置くべきです。この方法はリロードされないとコンパイラに教えます。だから、「inlined」の例になります。
class maf {

    public void setsize (int size) {
        _size = size;
    }

    private int _size;
}
訂正:
class daf_fixed {

    final public void setsize (int size) {
        _size = size;
    }

    private int _size;

}
六、不要なinstance of操作を避ける左のオブジェクトの静的なタイプが右の場合、instance of表現は常にtrueに戻ります。例:
public class uiso {

    public uiso () {}

}

class dog extends uiso {

    void method (dog dog, uiso u) {
        dog d = dog;
        if (d instanceof uiso) // always true.
            system.out.println("dog is a uiso");
        uiso uiso = u;
        if (uiso instanceof object) // always true.
            system.out.println("uiso is an object");
    }
}
訂正:不要なinstance of操作を削除します。
class dog extends uiso {

    void method () {
        dog d;
        system.out.println ("dog is an uiso");
        system.out.println ("uiso is an uiso");
    }
}
七、不要な造形操作を避けるすべての種類は直接または間接的にobjectから継承する。同じように、すべてのサブクラスにも父に等しいものが含まれています。子供から父親までの操作は不要です。
例:
class unc {

    string _id = "unc";
}

class dog extends unc {

    void method () {

        dog dog = new dog ();
        unc animal = (unc)dog; // not necessary.
        object o = (object)dog; // not necessary.
    }
}
訂正:
class dog extends unc {

    void method () {

        dog dog = new dog();
        unc animal = dog;
        object o = dog;
    }
}
八、単一の文字を検索するだけであれば、starts withの代わりにcharat()を使って一つの文字をパラメータとしてstarts with()を呼び出すのも良いですが、性能的にはstring appiを呼び出すのは間違いないです。例:
public class pcts {

private void method(string s) {

if (s.startswith("a")) { // violation

// ...

}

}

}
訂正は’starts with()’を’charat()’に置き換えます。
public class pcts {

private void method(string s) {

if ('a' == s.charat(0)) {

// ...

}

}

}
9、シフト動作を使用して、’a/b’動作の代わりに、/”は非常に高価な動作であり、シフト動作を使用するとより早く効果的である。例:
public class sdiv {

public static final int num = 16;

public void calculate(int a) {

int div = a / 4; // should be replaced with "a >> 2".

int div2 = a / 8; // should be replaced with "a >> 3".

int temp = a / 3;

}

}
訂正:
public class sdiv {

public static final int num = 16;

public void calculate(int a) {

int div = a >> 2;

int div2 = a >> 3;

int temp = a / 3; //          

}

}
十、シフト動作を’a*b’と同じにする。しかし、個人的には、非常に大きな循環内でない限り、性能は非常に重要であり、あなた自身が何をしているかをよく知っているからこそ、この方法が使えます。性能向上によるプログラムの遅読み性の低下はお得ではありません。例:
public class smul {

public void calculate(int a) {

int mul = a * 4; // should be replaced with "a << 2".

int mul2 = 8 * a; // should be replaced with "a << 3".

int temp = a * 3;

}

}
訂正:
package opt;

public class smul {

public void calculate(int a) {

int mul = a << 2;

int mul2 = a << 3;

int temp = a * 3; //     

}

}
十一、文字列を足すときは、’’代用’を使います。この文字列が1文字しかない場合、例:
public class str {

public void method(string s) {

string string = s + "d" // violation.

string = "abc" + "d" // violation.

}

}
訂正:文字の文字列を''に置換します。
public class str {

public void method(string s) {

string string = s + 'd'

string = "abc" + 'd'

}
}
十二、サイクルの中でsynchronized(同期)方法を呼び出さないでください。同期にはかなりの資料が必要です。循環の中で呼び出されるのは決していい考えではありません。
import java.util.vector;

public class syn {

public synchronized void method (object o) {

}

private void test () {

for (int i = 0; i < vector.size(); i++) {

method (vector.elementat(i)); // violation

}

}

private vector vector = new vector (5, 5);

}
訂正:循環体で同期方法を呼び出さないでください。同期が必要なら、以下の方法を勧めます。
import java.util.vector;

public class syn {

public void method (object o) {

}

private void test () {

synchronized{//              

for (int i = 0; i < vector.size(); i++) {

method (vector.elementat(i));

}

}

}

private vector vector = new vector (5, 5);

}
十三、try/catchブロックを取り出して循環してtry/catchブロックを循環体内に入れると、大きな影響性能があります。もしコンパイルジットがクローズされたり、或いはあなたが使っているのはジットを持たないjvmであれば、性能は21%以上下がることになります。例:
import java.io.fileinputstream;

public class try {

void method (fileinputstream fis) {

for (int i = 0; i < size; i++) {

try { // violation

_sum += fis.read();

} catch (exception e) {}

}

}

private int _sum;

}
訂正:
try/catchブロックをサイクルから取り除く
void method (fileinputstream fis) { try { for (int i = 0; i < size; i++) { _sum += fis.read(); } } catch (exception e) {} }
十四.bootlean値に対して、不必要な等式判断を避けるために、一つのbootlean値と一つのtrue値を比較するのは恒等的な操作(直接にこのbootlean変数の値に戻す)である。移行すると、bootleanの不必要な操作に対して少なくとも2つの利点がもたらされる。
public class ueq

{

boolean method (string string) {

return string.endswith ("a") == true; // violation

}

}
訂正:
class ueq_fixed {

boolean method (string string) {

return string.endswith ("a");

}

}
十五、定数文字列に対しては、「strigbuffer」定数文字列の代わりに「string」で長さを動的に変える必要がない。例:
public class usc {

string method () {

stringbuffer s = new stringbuffer ("hello");

string t = s + "world!";

return t;

}

}
  :  stringbuffer  stringstring      ,             。
十六、'stingtokenizer'を使って'indexof()'と'substring()の文字列の分析は多くの応用でよく見られます。indexof()とsubstring()を使って文字列を分析するとstindexoutofboundsexceptionになりやすいです。
public class ust {

void parsestring(string string) {

int index = 0;

while ((index = string.indexof(".", index)) != -1) {

system.out.println (string.substring(index, string.length()));

}

}

}
17、条件操作子を使用して「if(cond)return」を代替する。else return;構造条件演算子のより簡単な例:
public class if {

public int method(boolean isdone) {

if (isdone) {

return 0;

} else {

return 10;

}

}

}