1、避免使用多個 If-else 語句
我們在代碼中使用條件語句進行決策。條件語句不應該被過度使用。如果我們使用太多條件 if-else 語句,則會影響性能,因為 JVM 每次都必須比較條件。
如果在 for 循環、while 循環等循環語句中使用相同的内容,情況可能會變得更糟。
如果業務邏輯中有太多條件,請嘗試對條件進行分組并擷取布爾結果并在 if 語句中使用它。
另外,如果可能的話,我們可以考慮使用 switch 語句來代替多個 if-else。Switch 語句比 if-else 具有性能優勢。下面提供了示例作為示例,應避免如下情況:
例子:
if(條件1){
if(條件2){
if (條件3 || 條件4) { 執行..}
else{執行..}
注意: 應避免使用上述示例,并按如下方式使用:
布爾結果 = (條件1 && 條件2) && (條件3 || 條件4)
2、避免使用字元串對象進行連接配接
字元串是一個不可變類,由 String 建立的對象不能被重用。是以,如果我們需要建立一個大字元串,那麼使用“+”運算符連接配接 String 對象是不好的做法。
這将導緻建立多個 String 對象,進而導緻更多的堆記憶體使用。
在這種情況下,我們可以使用 StringBuilder 或 StringBuffer,前者優于後者,因為它由于非同步方法而具有性能優勢。
示例如下:
String str = str1+str2+str3;
注意: 應避免使用上述示例,并按如下方式使用:
StringBuilder strBuilder = new StringBuilder(“”);
strBuilder.append(str1).append(str2).append(str3);
字元串查詢 = strBuilder.toString();
3、避免編寫長方法
這些方法不應該太長,并且應該特定于執行單一功能。編寫代碼時使用單一職責原則。
這對于維護和性能都有好處,因為在類加載和方法調用期間,方法會加載到堆棧記憶體中。
如果方法很大且處理量過多,它們将消耗記憶體以及 CPU 周期來執行。
嘗試在适當的邏輯點将這些方法分解為更小的方法。
我建議在 IDE 中使用Find Bug 或 Sonar Cube插件。它們基本上表明了方法的認知複雜性何時從閥值開始增加。
4、避免在循環中擷取集合的大小
疊代任何集合時,都會在循環之前擷取集合的大小,而不會在疊代期間擷取它。下面提供了示例作為示例,應避免如下情況:
例子:
List<String> empListData = getEmpData ();
for ( int i = 0 ; i < empListData.size ( ); i++)
{
執行代碼 ..
}
注意:應避免使用上述示例,并按如下方式使用:
List<String> empListData= getEmpData();
int size = empListData.size();
for (int i = 0; i < 大小; i++) {
執行代碼..
}
5、避免使用BigInteger 和BigDecimal 類
BigDecimal 類為十進制值提供準确的精度。過度使用該對象會極大地影響性能,特别是當使用該對象來計算循環中的某些值時。
BigInteger 和 BigDecimal在 long 或 double 上使用大量記憶體來執行計算。
如果精度不是問題,或者如果我們确定計算值的範圍不會超過 long 或 double,我們可以避免使用 BigDecimal,而應該使用 long 或 double 并進行适當的轉換。
6、盡可能使用原始類型
使用原始資料類型比對象更好,因為原始類型資料存儲在堆棧記憶體中,而對象存儲在堆記憶體中。
如果可能,我們可以使用原始資料類型而不是對象,因為從堆棧記憶體通路資料比堆記憶體更快。
是以,使用 double 優于 Double 或使用 int 優于 Integer 總是有益的。
7、使用存儲過程代替查詢
最好編寫存儲過程而不是複雜而大的查詢并在處理時調用它們。
存儲過程作為對象存儲在資料庫中并進行預編譯。與具有相同業務邏輯的查詢相比,存儲過程的執行時間更短,因為每次通過應用程式調用查詢時都會編譯和執行查詢。
此外,存儲過程在資料傳輸和網絡流量方面具有優勢,因為我們不需要每次都将複雜的查詢傳輸到資料庫伺服器來執行。
8、避免經常建立大對象
有某些類在應用程式中充當資料持有者。這些對象很重,應避免多次建立它們。
例如使用者登入後的資料庫連接配接對象或會話對象。這些對象在建立時使用了大量資源。
我們應該重用這些對象,而不是建立它們,因為建立會由于更多的記憶體使用而極大地影響應用程式的性能。
我們應該盡可能使用單例模式來建立對象的單個執行個體,并在需要時重用它,或者克隆該對象而不是建立一個新對象。
9、在 Java 應用程式中謹慎使用“包含”
Lists、ArrayList 和Vectors都有一個 contains 方法,允許程式員檢查集合是否已經有類似的對象。可能正在疊代一個大樣本,并且經常需要在樣本中查找唯一對象的清單。代碼可能如下所示:
ArrayList al = new ArrayList();
for (int i=0; i < vars.size(); i++)
{
String obj = (String) vars.get(i);
if (!al.contains(obj))
{
al.add(obj);
}
}
從功能上講,這段代碼很好,但從性能的角度來看,需要在循環的每次疊代中檢查 ArrayList 是否包含該對象。contains 方法每次都會掃描整個 ArrayList。是以,随着 ArrayList 變大,性能損失也會增加。
最好先将所有樣本添加到 ArrayList,進行一次重複檢查,使用本質上提供唯一性的集合(例如 HashSet),然後建立唯一的 ArrayList 一次。現在不必對 ArrayList 進行數千次包含檢查,而是進行一次性重複檢查。
ArrayList al = new ArrayList();
…
for (int i=0; i < vars.size(); i++)
{
String obj = (String) vars.get(i);
al.add(obj);
}
al = removeDuplicates(al);
…
static ArrayList removeDuplicates(ArrayList list)
{
if (list == null || list.size() == 0)
{
return list;
}
Set set = new HashSet(list);
list.clear();
list.addAll(set);
return list;
}
下表顯示了我們的原始代碼和上面修改的代碼之間的時間差:
比較 | 100 | 1000 | 10000 | 100000 |
原始代碼 | 0ms | 5ms | 171ms | 49820ms |
修改代碼 | 0ms | 1ms | 7ms | 28ms |
10、使用PreparedStatement代替Statement
在通過應用程式執行 SQL 查詢時,我們使用 JDBC API 和類來實作同樣的目的。
對于參數化查詢執行來說, PreparedStatement比Statement更有優勢,因為preparedStatement 對象編譯一次并執行多次。
另一方面,Statement 對象在每次調用時都會被編譯和執行。此外,準備好的語句對象是安全的,可以避免 SQL 注入攻擊。
11、在查詢中選擇所需的列
在從資料庫擷取資料時,我們使用選擇查詢來擷取資料。避免選擇不需要進一步處理的列。
僅選擇我們需要進一步處理或在前端顯示的那些列。選擇太多列會導緻資料庫端的查詢執行延遲。
從資料庫中選擇資料時避免使用“*”。
此外,它還會增加從資料庫到應用程式的網絡流量,這是應該避免的。下面提供了示例作為示例,應避免如下情況:
例子:
select * from employee where emp_id = 100;
注意:應避免使用上述示例,并按如下方式使用:
從員工中選擇 emp_name、emp_age、emp_gender、emp_ocupation、emp_address,其中 emp_id = 100;
12、使用不必要的日志語句和不正确的日志級别
日志記錄是任何應用程式不可或缺的一部分,需要有效實施,以避免由于不正确的日志記錄和日志級别而導緻性能下降。
我們應該避免将大對象記錄到代碼中。日志記錄應限于特定參數。
此外,日志記錄級别應保持在較進階别,例如 DEBUG、ERROR,而不是 INFO。下面提供了示例作為示例,應避免如下情況:
例子:
Logger.debug ( "員工資訊:" + emp.toString ( ));
Logger.info ( "設定員工資料調用的方法:" + emp.getData ( ));
注意:應避免使用上述示例,并按如下方式使用:
Logger.debug(“員工資訊:” + emp.getName() + ”:登入ID:” + emp.getLoginId());
Logger.info(“設定員工資料所調用的方法”);
13、使用join連接配接擷取資料
從多個表擷取資料時,有必要在表上正确使用join聯接。如果未正确使用聯接或表未标準化,則會導緻查詢執行延遲,進而導緻應用程式性能下降。
避免使用子查詢而不是連接配接,因為子查詢比連接配接花費更多的執行時間。
在表中經常使用的列上建立索引,以提高查詢執行的性能并減少應用程式的延遲。
在 join 或 where 子句中始終首先使用主鍵。
14、使用 EntrySet 而不是 KeySet
如果在地圖上進行大量疊代,那麼EntrySet會比KeySet更好。EntrySet 可以在一秒鐘内比 KeySet 多運作 9000 次操作,是以将通過這種方式獲得更好的性能。
15、EnumSet 是枚舉值的最佳選擇
如果正在使用 Enum 值,那麼使用EnumSet更有意義。它允許比其他方法更快的計算。
EnumSet 的值以可預測的順序存儲,而其他方法(如 HashSet)需要更長的時間才能産生相同的結果。