天天看點

Java代碼優化小結(二)

(21)将常量聲明為static final,并以大寫命名

這樣在編譯期間就可以把這些内容放入常量池中,避免運作期間計算生成常量的值。另外,将常量的名字以大寫命名也可以友善區分出常量與變量

(22)不要建立一些不使用的對象,不要導入一些不使用的類

這毫無意義,如果代碼中出現”The value of the local variable i is not used”、”The import java.util is never used”,那麼請删除這些無用的内容

(23)程式運作過程中避免使用反射

反射是Java提供給使用者一個很強大的功能,功能強大往往意味着效率不高。不建議在程式運作過程中使用尤其是頻繁使用反射機制,特别是Method的invoke方法,如果确實有必要,一種建議性的做法是将那些需要通過反射加載的類在項目啟動的時候通過反射執行個體化出一個對象并放入記憶體—-使用者隻關心和對端互動的時候擷取最快的響應速度,并不關心對端的項目啟動花多久時間。

(24)使用資料庫連接配接池和線程池

這兩個池都是用于重用對象的,前者可以避免頻繁地打開和關閉連接配接,後者可以避免頻繁地建立和銷毀線程。

(25)使用帶緩沖的輸入輸出流進行IO操作

帶緩沖的輸入輸出流,即BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream,這可以極大地提升IO效率。

(26)順序插入和随機通路比較多的場景使用ArrayList,元素删除和中間插入比較多的場景使用LinkedList

這個,了解ArrayList和LinkedList的原理就知道了。

(27)不要讓public方法中有太多的形參

public方法即對外提供的方法,如果給這些方法太多形參的話主要有兩點壞處:

違反了面向對象的程式設計思想,Java講求一切都是對象,太多的形參,和面向對象的程式設計思想并不契合

參數太多勢必導緻方法調用的出錯機率增加

至于這個”太多”指的是多少個,3、4個吧。比如我們用JDBC寫一個insertStudentInfo方法,有10個學生資訊字段要插如Student表中,可以把這10個參數封裝在一個實體類中,作為insert方法的形參。

(28)字元串變量和字元串常量equals的時候将字元串常量寫在前面

這是一個比較常見的小技巧了,如果有以下代碼:

1 String str = "123" ;
 2 if (str.equals( "123" )){
 3     ...
 4 }
 5 
 6 //建議修改為:
 7 String str = "123" ;
 8 if ( "123" .equals(str)){
 9     ...
10 }      

這麼做主要是可以避免空指針異常。

(29)請知道,在java中if (i == 1)和if (1 == i)是沒有差別的,但從閱讀習慣上講,建議使用前者

(30)不要對數組使用toString()方法

看一下對數組使用toString()列印出來的是什麼:

public static void main(String[] args){
    int [] is = new int []{ 1 , 2 , 3 };
    System.out.println(is.toString());
}
//結果是:[I @18a992f      

本意是想列印出數組内容,卻有可能因為數組引用is為空而導緻空指針異常。不過雖然對數組toString()沒有意義,但是對集合toString()是可以列印出集合裡面的内容的,因為集合的父類AbstractCollections<E>重寫了Object的toString()方法。

(31)不要對超出範圍的基本資料類型做向下強制轉型

這絕不會得到想要的結果:

1 public static void main(String[] args){
2     long l = 12345678901234L;
3     int i = ( int )l;
4     System.out.println(i);
5 }      

我們可能期望得到其中的某幾位,但是結果卻是:1942892530

轉換成二進制:Java中long是8個位元組64位的,int型資料是4個位元組32位的,從低位取出long轉換的這串二進制資料的前32位。

得到兩個結論:

  • 1、整型預設的資料類型是int,long l = 12345678901234L,這個數字已經超出了int的範圍了,是以最後有一個L,表示這是一個long型數。順便,浮點型的預設類型是double,是以定義float的時候要寫成”"float f = 3.5f”
  • 2、接下來再寫一句”int ii = l + i;”會報錯,因為long + int是一個long,不能指派給int。

(32)公用的集合類中不使用的資料一定要及時remove掉

如果一個集合類是公用的(也就是說不是方法裡面的屬性),那麼這個集合裡面的元素是不會自動釋放的,因為始終有引用指向它們。是以,如果公用集合裡面的某些資料不使用而不去remove掉它們,那麼将會造成這個公用集合不斷增大,使得系統有記憶體洩露的隐患。

(33)把一個基本資料類型轉為字元串,基本資料類型.toString()是最快的方式、String.valueOf(資料)次之、資料+”"最慢

遇到把一個基本資料類型轉為String的時候,優先考慮使用toString()方法。至于為什麼,很簡單:

String.valueOf()方法底層調用了Integer.toString()方法,但是會在調用前做空判斷

Integer.toString()方法就不說了,直接調用了

i + “”底層使用了StringBuilder實作,先用append方法拼接,再用toString()方法擷取字元串

(34)使用最有效率的方式去周遊Map

周遊Map的方式有很多,通常場景下我們需要的是周遊Map中的Key和Value,那麼推薦使用的、效率最高的方式是:

1 public static void main(String[] args){
 2     HashMap<String, String> hm = new HashMap<String, String>();
 3     hm.put( "111" , "222" );
 4     Set<Map.Entry<String, String>> entrySet = hm.entrySet();
 5     Iterator<Map.Entry<String, String>> iter = entrySet.iterator();
 6     while (iter.hasNext()){
 7     Map.Entry<String, String> entry = iter.next();
 8     System.out.println(entry.getKey() + " " + entry.getValue());
 9     }
10 }      

如果你隻是想周遊一下這個Map的key值,那用”Set<String> keySet = hm.keySet();”會比較合适一些。

補充:

  下面是用keySet()和enrtySet()測試兩者周遊集合效率的測代碼

1 import java.util.HashMap;
 2 import java.util.Iterator;
 3 import java.util.Map;
 4 
 5 /**
 6  * @Author: jackpotHan
 7  * @Date: 2018/7/18 16:53
 8  * @Description:
 9  */
10 public class MapTest {
11 
12     public static void main(String[] args) {       
13 
14         Map<String,String> keySetMap = new HashMap<>();
15 
16         Map<String,String> entrySetMap = new HashMap<>();
17 
18         for (int i = 0; i < 1000000; i++) {
19             keySetMap.put("" + i, "keySet");
20         }
21         for (int j = 0; j < 1000000; j++) {
22             entrySetMap.put("" + j, "entrySet");
23         }
24 
25         Long startTime1 = System.currentTimeMillis();
26         Iterator<String> keySetIterator = keySetMap.keySet().iterator();
27         while (keySetIterator.hasNext()) {
28             String key = keySetIterator.next();
29             String value = keySetMap.get(key);
30             System.out.println(value);
31         }
32         Long keySetTime = System.currentTimeMillis() - startTime1;
33         long startTime2 = System.currentTimeMillis();
34         Iterator<Map.Entry<String, String>> entryKeyIterator = entrySetMap
35                 .entrySet().iterator();
36         while (entryKeyIterator.hasNext()) {
37             Map.Entry<String, String> e = entryKeyIterator.next();
38             System.out.println(e.getValue());
39         }
40         Long entryTime = System.currentTimeMillis() - startTime2;
41 
42         System.out.println("keySetSpentTime:" + keySetTime);
43         System.out.println("enrtySetSpentTime:" + entryTime);
44 
45     }
46 }
47 //兩者耗時對比:
48 //    keySetSpentTime:6509
49 //    enrtySetSpentTime:6477      
上一篇: Java8 Stream