java程式碼優化
1:多餘的 if/else,對於boolean值,避免不必要的等式判斷。
反例:
boolean ret;
int i=0;
if(i==0)
{
ret=true;
}
else
{
ret=false;
}
類似上面這種寫法if/else 可以簡寫:
int i=0;
boolean ret=(i==0)?true:false;
2:多餘的 else
public static String Login(String name) { String reponseJson=""; if(name==null) { reponseJson= "請輸入使用者名稱"; } else { //登入方法 reponseJson=""; } return reponseJson; }
完全可以提前 return,進而幹掉 else 分支
public static String Login(String name)
{
String reponseJson="";
if(name==null)
{
reponseJson= "請輸入使用者名稱";
}
//登入方法
reponseJson="";
return reponseJson;
}
- 簡單就是美,程式碼寫的越少,犯錯的機率就越小。
- 提前終止程式,絕大多數情況下,會節省很多不必要的開銷(會減少很多無效的判斷,減少無效變數、物件的建立)。
- 每種程式語言都離不開 if/else 進行條件判斷,如果在編碼時,存在過多的 if/else 巢狀,程式碼的可讀性就會下降,後期維護難度就會大大提高。
3:隨處可見的判空邏輯。
if(name == null || "".equals(name)) {
}
很多時候都需要做非空檢查
確實有點不雅觀。
很多同學會想著,自己封裝 StringUtils 工具類
可以引用
import org.apache.commons.lang3.StringUtils;
if(StringUtils.isBlank(name))
{
return "";
}
4:完成物件間的屬性 Copy,編寫冗長的程式碼。
BeanUtils.copyProperties(EntityOld,EntityNew);
5for
所以例如下面的操作:
for (int i = 0; i < list.size(); i++)
{...}
建議替換為:
for (int i = 0, length = list.size(); i < length; i++)
{...}
6 儘量採用懶載入的策略,即在需要的時候才建立
例如:
String str = "aaa";
if (i == 1)
{
list.add(str);
}
建議替換為:
if (i == 1)
{
String str = "aaa";
list.add(str);
}
7當複製大量資料時,使用System.arraycopy()命令
8 迴圈內不要不斷建立物件引用
例如:
for (int i = 1; i <= counts; i++)
{
Object obj = new Object();
}
這種做法會導致記憶體中有count份Object物件引用存在,count很大的話,就耗費記憶體了,建議為改為:
Object obj = null;
for (int i = 0; i <= counts; i++)
{
obj = new Object();
}
9 儘量避免隨意使用靜態變數
要知道,當某個物件被定義為static的變數所引用,那麼gc通常是不會回收這個物件所佔有的堆記憶體的,如:
public class A
{
private static B b = new B();
}
10 將常量宣告為static final,並以大寫命名
這樣在編譯期間就可以把這些內容放入常量池中,避免執行期間計算生成常量的值。另外,將常量的名字以大寫命名也可以方便區分出常量與變
11 字串變數和字串常量equals的時候將字串常量寫在前面
這是一個比較常見的小技巧了,如果有以下程式碼:
String str = "123";
if (str.equals("123"))
{
...
}
建議修改為:
String str = "123";
if ("123".equals(str))
{
...
}
這麼做主要是可以避免空指標異常
12請知道,在java中if (i == 1)和if (1 == i)是沒有區別的,但從閱讀習慣上講,建議使用前者
13不要對陣列使用toString()方法
看一下對陣列使用toString()打印出來的是什麼:
public static void main(String[] args) {
int[] is = new int[]{2, 5, 3};
System.out.println(is.toString());
}
14不要對超出範圍的基本資料型別做向下強制轉型
這絕不會得到想要的結果:
public static void main(String[] args)
{
long l = 123456789645454L;
int i = (int)l;
System.out.println(i);
}
15 公用的集合類中不使用的資料一定要及時remove掉
16把一個基本資料型別轉為字串,基本資料型別.toString()是最快的方式、String.valueOf(資料)次之、資料+""最慢
17使用最有效率的方式去遍歷Map
遍歷Map的方式有很多,通常場景下我們需要的是遍歷Map中的Key和Value,那麼推薦使用的、效率最高的方式是:
public static void main(String[] args)
{
HashMap<String, String> hmp = new HashMap<String, String>();
hmp.put("324", "234");
hmp.put("33524", "234");
long startTime=0;
long endTime=0;
startTime = System.currentTimeMillis();
Set<Map.Entry<String, String>> entrySet = hmp.entrySet();
Iterator<Map.Entry<String, String>> iter = entrySet.iterator();
while (iter.hasNext())
{
Map.Entry<String, String> entry = iter.next();
System.out.println(entry.getKey() + "\t" + entry.getValue());
}
endTime = System.currentTimeMillis();
System.out.println("1程式執行時間:" + (endTime - startTime) + "ms");
startTime = System.currentTimeMillis();
Iterator<Map.Entry<String, String>> iterator = hmp.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> entry = iterator.next();
System.out.println("key"+ entry.getKey() + "\t" + entry.getValue());
}
endTime = System.currentTimeMillis();
System.out.println("2程式執行時間:" + (endTime - startTime) + "ms");
startTime = System.currentTimeMillis();
for (String key : hmp.keySet()) {
System.out.println("key"+key + "\t" + hmp.get(key));
}
endTime = System.currentTimeMillis();
System.out.println("3程式執行時間:" + (endTime - startTime) + "ms");
}
結果:
33524 234
324 234
程式執行時間:2ms
key33524 234
key324 234
程式執行時間:0ms
key33524 234
key324 234
程式執行時間:1ms
18對資源的close()建議分開操作
19 對於ThreadLocal使用前或者使用後一定要先remove
20 long或者Long初始賦值時,使用大寫的L而不是小寫的l,因為字母l極易與數字1混淆,這個點非常細節,值得注意
21 所有重寫的方法必須保留@Override註解
22 迴圈體內不要使用"+"進行字串拼接,而直接使用StringBuilder不斷append
23在存在大量字串拼接或者大型字串拼接的時候,儘量使用StringBuilder和StringBuffer,確定 StringBuffer的容量
24避免Random例項被多執行緒使用,雖然共享該例項是執行緒安全的,但會因競爭同一seed 導致的效能下降,JDK7之後,可以使用ThreadLocalRandom來獲取隨機數
25靜態類、單例類、工廠類將它們的建構函式置為private
26時間選擇 : 迴圈中用System.nanoTime因為精度高,平時用System.currentTimeMillis()能和data轉換
27.float和double 要效能和記憶體用float,要精度高用double
28.集合初始化儘量指定大小
int[] arr=new int[]{1,2,3};
List<Integer> list=new ArrayList<>(arr.length);
29.長整型常量後新增大寫 L
在使用長整型常量值時,後面需要新增 L ,必須是大寫的 L ,不能是小寫的 l ,小寫 l 容易跟數字 1 混淆而造成誤解。
30.建議使用 try-with-resources 語句
Java 7 中引入了 try-with-resources 語句,該語句能保證將相關資源關閉,優於原來的 try-catch-finally 語句,並且使程式程式碼更安全更簡潔。
31.刪除未使用的私有方法和欄位
32.刪除未使用的區域性變數
33公有靜態常量應該通過類訪問
34.禁止使用構造方法 BigDecimal(double)
35.返回空陣列和空集合而不是 null
反例:
private static List<Integer> getList()
{
return null;
}
正例:
private static List<Integer> getList()
{
return Collections.emptyList();
}
36.列舉的屬性欄位必須是私有不可變
37.小心 String.split(String regex)
字串 String 的 split 方法,傳入的分隔字串是正則表示式!部分關鍵字(比如.[]()\|等)需要轉義
38如果只是查詢單個字元的話,用charAt()代替startsWith()
39 使用移位操作來代替'a / b'操作
"/"是一個很“昂貴”的操作,使用移位操作將會更快更有效。
例子:
private static void calculates(int a)
{
int div = a /4;
int div2 = a / 8;
int temp = a / 3;
}
更正:
public static void calculate2(int a) {
int div = a >> 2;
int div2 = a >> 4;
int temp = a / 3;
}
40使用移位操作代替'a * b'
例子:
private static void calculates(int a)
{
int div = a *4;
int div2 = a* 8;
int temp = a * 3;
}
更正:
public static void calculate2(int a) {
int div = a << 2;
int div2 = a << 4;
int temp = a* 3;
}
41在字串相加的時候,使用 ' ' 代替 " ",如果該字串只有一個字元的話
例子:
private static void Str(String s)
{
String string = s + "d"; // violation.
string = "abc" + "d"; // violation.
}
更正:
public static void Str2(String s) {
String string = s + 'd'; // violation.
string = "abc" + 'd'; // violation.
}
42把try/catch塊放入迴圈體內,會極大的影響效能,如果編譯JIT被關閉或者你所使用的是一個不帶JIT的JVM,效能會將下降21%之多!
43儘可能的使用棧變數,訪問靜態變數和例項變數將會比訪問區域性變數多耗費2-3個時鐘週期