ホームページ  >  記事  >  Java  >  Java コードを最適化する方法と、仕事で利用できる実践的なヒントは何ですか?

Java コードを最適化する方法と、仕事で利用できる実践的なヒントは何ですか?

王林
王林転載
2023-05-09 08:16:071168ブラウズ

1. クラス メンバーとメソッドの可視性を最小限に抑える

例:プライベート メソッドの場合、削除したい場合は削除します

If a publicservice メソッド、または public メンバー変数は、深く考えずに削除する必要があります。

2. 乗算と除算の代わりに変位演算を使用する

コンピュータはバイナリ表現を使用するため、変位演算によりパフォーマンスが大幅に向上します。

> 右シフトは 2 で割ることと同等;

>>> 符号なし右シフトは次と同等2 で除算しますが、符号ビットは無視され、空のビットは 0 で埋められます。

a = val << 3;
b = val >> 1;

3. 変数の繰り返し計算を最小限に抑える

スタック フレームの作成、メソッド呼び出し時のシーンの保護、シーンの復元など、メソッドの呼び出しにはコストがかかることがわかっています。

//反例
for (int i = 0; i < list.size(); i++) {
  System.out.println("result");
}
//正例
for (int i = 0, length = list.size(); i < length; i++) {
  System.out.println("result");
}

list.size() が非常に大きい場合、消費量が大幅に削減されます。

4. RuntimeException をキャッチしない

RuntimeException は catch ステートメントによってキャッチされるべきではなく、コーディング手段によって回避される必要があります。

次のコードに示すように、リストで配列範囲外の例外が発生する可能性があります。

例外が発生したときに例外をキャッチするのを待つのではなく、範囲外かどうかをコードを通じて事前に判断できます。

この方法を事前に判断すると、コードがより洗練され、効率的になります。

public String test1(List<String> list, int index) {
    try {
        return list.get(index);
    } catch (IndexOutOfBoundsException ex) {
        return null;
    }
}
//正例
public String test2(List<String> list, int index) {
    if (index >= list.size() || index < 0) {
        return null;
    }
    return list.get(index);
}

5. ローカル変数を使用してヒープへの割り当てを回避します

ヒープ リソースは複数のスレッドで共有され、ガベージ コレクターが動作する主な領域であるため、オブジェクトが多すぎると GC プレッシャーが発生します。 . 、ローカル変数を介して変数をスタック上に割り当てることができます。このようにして、メソッドの実行が完了すると変数が破棄されるため、GC への負担が軽減されます。

6. 変数のスコープを減らす

変数のスコープに注意し、オブジェクトの作成を最小限に抑えます。

次のコードに示すように、変数 s はメソッドが入力されるたびに作成され、if ステートメント内に移動できます。

public void test(String str) {
    final int s = 100;
    if (!StringUtils.isEmpty(str)) {
        int result = s * s;
    }
}

7. 遅延読み込み戦略

遅延読み込み戦略を採用し、必要な場合にのみ作成するようにしてください

String str = "月伴飞鱼";
if (name == "公众号") {
  list.add(str);
}
if (name == "公众号") {
  String str = "月伴飞鱼";
  list.add(str);
}

8. クラス名を使用して静的変数に直接アクセスします

オブジェクトを使用して静的変数にアクセスします。このメソッドでは、アドレス指定操作が 1 つ追加されます。最初に変数に対応するクラスを見つけてから、そのクラスに対応する変数を見つける必要があります。

 // 反例
int i = objectA.staticMethod();
 // 正例
int i = ClassA.staticMethod();

9. 文字列の結合には StringBuilder を使用します

文字列の結合には StringBuilder または StringBuffer を使用し、数字は使用しないでください。

//反例
public class StringTest {
    @Test
    public void testStringPlus() {
        String str = "111";
        str += "222";
        str += "333";
        System.out.println(str);
    }
}
//正例
public class TestMain {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("111");
        sb.append("222");
        sb.append(333);
        System.out.println(sb.toString());
    }
}

10. オブジェクトの HashCode を書き換えます

単純に固定値を返すのではなく、オブジェクトの HashCode を書き換えます

一部の学生は、HashCode メソッドと Equals メソッドのオーバーライドを開発しています。 、HashCode の値を固定の 0 に返しますが、これは不適切です。

これらのオブジェクトが HashMap に格納されると、パフォーマンスが非常に低下します。これは、HashMap が HashCode を通じてハッシュ スロットを見つけ、この場合に限り、リンクリストや赤黒ツリーを用いてノードを整理し、固定的に0を返すことになり、ハッシュアドレッシング機能を無効にすることと同じになります。

11. HashMapなどのコレクションの初期化

HashMapなどのコレクションを初期化する場合は、初期値のサイズを指定します

このようなオブジェクトはArrayList、StringBuilder、初期値を指定することで、拡張によるパフォーマンスの低下を軽減できます。

初期値サイズの計算:

Java コードを最適化する方法と、仕事で利用できる実践的なヒントは何ですか?

12. ループ内にオブジェクト参照を作成

ループ内 オブジェクト参照を連続的に作成しないでください

//反例
for (int i = 1; i <= size; i++) {
    Object obj = new Object();    
}
//正例
Object obj = null;
for (int i = 0; i <= size; i++) {
    obj = new Object();
}

最初のメソッドでは、size Object のオブジェクト参照がメモリ上に存在します。サイズが大きいとメモリを消費します。

13. EntrySet メソッドを使用してマップを移動する

EntrySet メソッドを使用すると、セット オブジェクトを直接返すことができ、これを直接使用できます。また、KeySet メソッドを使用するとキーのコレクションを取得できます。別の取得操作を実行すると、操作ステップが 1 つ追加されるため、マップを走査するには EntrySet メソッドを使用することをお勧めします。

Set<Map.Entry<String, String>> entryseSet = nmap.entrySet();
for (Map.Entry<String, String> entry : entryseSet) {
    System.out.println(entry.getKey()+","+entry.getValue());
}

14. 複数のスレッドで同じ Random を使用しないでください

Random クラスのシードは同時アクセス中に競合するため、パフォーマンスが低下します。 -スレッド環境の種類。

 public static void main(String[] args) {
        ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
        Thread thread1 = new Thread(()->{
            for (int i=0;i<10;i++){
                System.out.println("Thread1:"+threadLocalRandom.nextInt(10));
            }
        });
        Thread thread2 = new Thread(()->{
            for (int i=0;i<10;i++){
                System.out.println("Thread2:"+threadLocalRandom.nextInt(10));
            }
        });
        thread1.start();
        thread2.start();
    }

15.自動インクリメントには LongAddr を使用することをお勧めします

自動インクリメント操作では、synchronized volatile # の組み合わせによってスレッド セーフを制御できます。 ## または、アトミック クラス (AtomicLong など) を使用できます。

後者の速度は前者よりも高く、

AtomicLong 比較と置換に CAS を使用すると、スレッドが多い場合に無効なスピンが多すぎます。LongAdder を使用して AtomicLong を置き換えることができます。さらなる進化とパフォーマンス向上を目指します。

public class Test {
    public int longAdderTest(Blackhole blackhole) throws InterruptedException {
        LongAdder longAdder = new LongAdder();
        for (int i = 0; i < 1024; i++) {
            longAdder.add(1);
        }
        return longAdder.intValue();
    }
}

16. プログラムでのリフレクションの使用を減らす

リフレクション関数は非常に強力ですが、バイトコードを解析することによって実装されており、パフォーマンスはあまり理想的ではありません。

実際には、リフレクションの実行処理(メソッドなど)をキャッシュしたり、多重化を利用してリフレクションを高速化するなど、リフレクションの最適化手法は数多くあります。

Java 7.0 以降、新しいパッケージ

java.lang.invoke が追加され、JVM レベルからの文字列の直接受け渡しをサポートするための新しい JVM バイトコード命令 invokedynamic が追加されました。ターゲットメソッド。

以上がJava コードを最適化する方法と、仕事で利用できる実践的なヒントは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。