この記事の例では、Java パフォーマンス最適化テクニックを要約しています。皆さんの参考に共有してください。具体的な分析は次のとおりです。
ここでは、ほとんどの Java アプリケーションに適したいくつかの書籍とネットワーク リソースを参照します。
JAVA プログラムでは、パフォーマンスの問題の原因のほとんどは JAVA 言語にあるのではなく、プログラム自体にあります。良いコーディング習慣を身に付けることは非常に重要であり、プログラムのパフォーマンスを大幅に向上させることができます。
1. Final 修飾子を使用してみます。
Final 修飾子を持つクラスは派生されません。 JAVA コア API には、java.lang.String など、final を適用する例が多数あります。 String クラスに Final を指定すると、ユーザーは length() メソッドをオーバーライドできなくなります。さらに、クラスが Final の場合、そのクラスのすべてのメソッドが Final になります。 Java コンパイラは、すべての最終メソッドをインライン化する機会を探します (これは特定のコンパイラの実装によって異なります)。これにより、パフォーマンスが平均 50% 向上します。
2. オブジェクトを再利用してみます。
特に String オブジェクトを使用する場合、文字列の連結が発生する場合は、代わりに StringBuffer を使用する必要があります。これは、システムがオブジェクトの生成に時間を費やすだけでなく、将来的にはこれらのオブジェクトのガベージ コレクションや処理にも時間がかかる可能性があるためです。したがって、生成するオブジェクトが多すぎると、プログラムのパフォーマンスに大きな影響を与えます。
3. ローカル変数を使用してみます。
メソッドの呼び出し時に渡されるパラメーターと呼び出し中に作成される一時変数はスタック (Stack) に保存されるため、処理が高速になります。静的変数、インスタンス変数などの他の変数はヒープ内に作成されるため、速度が遅くなります。
4. 変数を繰り返し初期化しないでください。
デフォルトでは、クラスのコンストラクターを呼び出すと、Java は変数を特定の値に初期化し、すべてのオブジェクトは null に設定され、整数変数は 0 に設定され、float 変数と double 変数は 0.0 に設定され、論理値は に設定されます。間違い。これは、クラスが別のクラスから派生する場合に特に注意する必要があります。これは、 new キーワードを使用してオブジェクトが作成されると、コンストラクター チェーン内のすべてのコンストラクターが自動的に呼び出されるからです。
ここで注意事項があります。メンバー変数の初期値を設定するときに他のメソッドを呼び出す必要がある場合は、値を割り当てるためにメソッドを直接呼び出すと null がスローされる可能性があるため、それを initXXX() などのメソッドに入れるのが最善です。クラスが初期化されていないため、ポインタ例外が発生します。 public int state = this.getState();
5. Java+Oracle アプリケーション システムの開発では、Oracle パーサーの解析負担を軽減するために、Java に埋め込まれた SQL 言語をできるだけ大文字にする必要があります。
6. Java プログラミング プロセス中に、データベース接続と I/O ストリーム操作を実行し、使用後はリソースを解放するためにそれらを閉じます。これらの大きなオブジェクトを操作すると、システムに多大なオーバーヘッドが発生するためです。
7. オブジェクトを過剰に作成すると、大量のシステム メモリが消費され、深刻な場合にはメモリ リークが発生する可能性があるため、期限切れのオブジェクトを適時にリサイクルすることが非常に重要です。
JVM の GC はあまりスマートではないため、オブジェクトの使用後に手動で null に設定することをお勧めします。
8. 同期メカニズムを使用する場合は、コード ブロック同期ではなくメソッド同期を使用するようにしてください。
9. 変数の二重カウントを最小限に抑えます。
例えば
for(int i=0;i<list.size();i++)
に変更する必要があります
for(int i=0,len=list.size();i<len;i++)
10. 必要なときだけ作成する戦略を採用します。
例えば:
文字列 str="abc";if(i==1){ list.add(str);}
次のように変更する必要があります。
if(i==1){文字列 str="abc"; list.add(str);}
11. 例外はパフォーマンスに悪影響を与えるため、例外の使用には注意してください。
例外をスローすると、まず新しいオブジェクトが作成されます。 Throwable インターフェイスのコンストラクターは、fillInStackTrace() という名前のローカル メソッドを呼び出します。fillInStackTrace() メソッドはスタックをチェックし、呼び出しトレース情報を収集します。処理中に新しいオブジェクトが作成されるため、例外がスローされるたびに、VM はコール スタックを調整する必要があります。
例外はエラー処理にのみ使用する必要があり、プログラム フローの制御には使用しないでください。
12. Try/Catch ステートメントをループ内で使用しないでください。Try/Catch はループの最も外側のレベルに配置する必要があります。
Error は、システム エラーまたは仮想マシン エラーを取得するためのクラスです。すべてのエラー例外を取得できるわけではありません。仮想マシンがエラー例外を報告した場合、それを取得するには Error を使用する必要があります。
13. コンストラクターを通じて StringBuffer の初期容量を設定すると、パフォーマンスが大幅に向上します。
StringBuffer のデフォルトの容量は 16 です。StringBuffer の容量が最大容量に達すると、その容量は現在の容量の 2 倍 + 2 (2*n+2) に増加します。 StringBuffer が最大容量に達するたびに、新しいオブジェクトの配列を作成し、古いオブジェクトの配列をコピーする必要があり、多くの時間が無駄になります。したがって、StringBuffer には適切な初期容量値を設定する必要があります。
14. java.util.Vector を合理的に使用します。
Vector は StringBuffer に似ています。容量が拡張されるたびに、既存のすべての要素を新しい記憶領域に割り当てる必要があります。 Vector のデフォルトの保存容量は 10 要素ですが、容量は 2 倍になります。
Vector.add(index,obj) このメソッドは要素 obj をインデックス位置に挿入できますが、インデックス以降の要素は 1 つ下に移動する (インデックスを 1 増やす) 必要があります。 必要な場合を除き、パフォーマンスに悪影響を及ぼします。
同じルールが、このベクトル内の指定された位置にある要素を削除する、remove(intindex) メソッドにも適用されます。後続のすべての要素を左にシフトします (インデックスを 1 ずつ減らします)。このベクトルから削除された要素を返します。したがって、ベクトルの最後の要素を削除する方が、最初の要素を削除するよりもコストが大幅に低くなります。すべての要素を削除するには、removeAllElements() メソッドを使用することをお勧めします。
ベクトル内の要素を削除したい場合は、vector.remove(obj); を使用できます。要素の位置を自分で取得してから削除する必要はありません。たとえば、 intindex =indexOf(obj);索引);
15. 大量のデータをコピーする場合は、System.arraycopy(); を使用します。
16. コードの可読性を高めるためのコードのリファクタリング。
17. new キーワードを使用せずにオブジェクトのインスタンスを作成します。
new キーワードを使用してクラスのインスタンスを作成すると、コンストラクター チェーン内のすべてのコンストラクターが自動的に呼び出されます。ただし、オブジェクトが Cloneable インターフェイスを実装している場合は、その clone() メソッドを呼び出すことができます。 clone() メソッドはクラス コンストラクターを呼び出しません。
以下は、Factory パターンの典型的な実装です。
public static Credit getNewCredit(){ return new Credit();} 改良されたコードでは、clone() メソッドを使用します。 private static Credit BaseCredit = new Credit(); public static Credit getNewCredit(){ return (Credit)BaseCredit.clone() ;}
18. ディスプレイスメントを乗除算に使用できる場合は、可能な限りディスプレイスメントを使用する必要がありますが、ディスプレイスメントの操作は直感的ではなく、理解しにくいため、コメントを追加するのが最善です。
19. 配列を public static Final として宣言しないでください。
20.HaspMap トラバーサル。
Map<String, String[]> paraMap = new HashMap<String, String[]>();for( Entry<String, String[]> エントリ : paraMap.entrySet() ){ String appFieldDefId =entry.getKey(); String[] 値 =entry.getValue();}
ハッシュ値を利用して該当するEntryを取得し比較結果を取得後、キーと値を直接取得します。
21. 配列 (array) と ArrayList の使用。
Array 配列は最も効率的ですが、その容量は固定されており、動的に変更できません。ArrayList の容量は動的に増加できますが、効率が犠牲になります。
22. 単一スレッドでは HashMap と ArrayList を使用する必要があります。必要な場合を除き、HashTable と Vector を使用することは推奨されません。これらは同期メカニズムを使用するため、パフォーマンスが低下します。
23. StringBuffer と StringBuilder の違いは次のとおりです。 java.lang.StringBuffer は、スレッドセーフな変数文字シーケンスです。 String に似た文字列バッファですが、変更できません。 StringBuilder StringBuilder クラスは、すべて同じ操作をサポートしますが、同期を実行しないため高速であるため、通常はこのクラスよりも優先して使用する必要があります。より良いパフォーマンスを得るには、StringBuffer または StringBuilder を構築するときにその容量を指定するようにしてください。もちろん16文字以内であれば必要ありません。
同じ状況下では、StringBuilder を使用すると、StringBuffer を使用した場合に比べて 10% ~ 15% のパフォーマンス向上しか達成できませんが、マルチスレッドのセキュリティが確保されないリスクがあります。総合的に検討した結果、StringBuffer を使用することをお勧めします。
24. オブジェクトの代わりに基本的なデータ型を使用するようにしてください。
25. 三角関数の問題を解くために表を参照するなど、複雑な関数計算の代わりに単純な数値計算を使用します。
26. 具体的なアナロジーを使用すると、インターフェイスを使用するより効率的ですが、構造の柔軟性が低下しますが、最新の IDE はこの問題を解決できます。
27. 静的メソッドの使用を検討する
オブジェクトの外部にアクセスする必要がない場合は、メソッドを静的にしてください。仮想関数ガイド テーブルを必要としないため、より高速に呼び出されます。この同僚も、メソッドの性質を区別する方法を教えてくれるので、このメソッドを呼び出してもオブジェクトの状態は変更されません。
28. 組み込みの GET および SET メソッドの使用は可能な限り避けるべきです。
Android プログラミングでは、仮想メソッドの呼び出しに多額のコストがかかり、インスタンス属性クエリよりも高価になります。 get メソッドと set メソッドはアウトソーシング呼び出しの場合にのみ使用する必要がありますが、内部で呼び出す場合は直接呼び出す必要があります。
29. 列挙型と浮動小数点数の使用は避けてください。
30. 2 次元配列は 1 次元配列より多くのメモリ領域を占有し、計算量は約 10 倍になります。
31. SQLite データベースはテーブル全体のすべてのデータを非常に速く読み取りますが、条件付きクエリには 30 ~ 50 ミリ秒かかります。これを実行するときは、特にネストされた検索の使用をできるだけ少なくするように注意する必要があります。
この記事が皆さんの Java プログラミングに役立つことを願っています。