相信每個人都喜歡看簡潔易懂的代碼,代碼可讀性也是衡量代碼質量的重要標準之一,而本文則通過十個具體的編程小技巧(部分技巧并不局限于Java),希望能夠幫助到你,
1. 使用三元運算式
考慮以下代碼:
public boolean isOdd(int num) {
if (num % 2 == 1) {
return true;
} else {
return false;
}
}
我們可能會經常見到類似上面的代碼,只需要一次簡單的if ... else ...判斷,而判斷所得到的內容也很簡單,在這種時候,我們就可以使用三元運算式來簡化我們的代碼,就像下面這樣:
public boolean isOdd(int num) {
return num % 2 == 1 ? true : false;
}
可以發現,通過使用... ? ... : ...三元運算式,我們能夠寫出更加簡單的代碼,當然這個代碼仍然不夠簡潔,在接下來第二點會進行討論,這里先討論三元表示式,雖然三元表示式可以簡化我們的代碼,在很多時候也能夠簡化我們的代碼,但是當判斷的情況過多并且陳述句較長的時候,我們就不應該使用三元運算式了,就像下面這種情況,我們就不應該采用三元運算式:
public int getMaxDays(int year, int month) {
// 當條件過多時, 使用三元表示就無法體現發揮簡潔的優勢了,我們應該考慮其它的方法
return month == 2 ? (isLeapYear(year) ? 29 : 28) :
(month == 4 || month == 6 || month == 9 || month == 11) ? 30 : 31;
}
private boolean isLeapYear(int year) {
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}
2. 簡化布爾條件運算式
再次考慮1中的代碼:
public boolean isOdd(int num) {
return num % 2 == 1 ? true : false;
}
由于我們回傳的結果是布林值,所以在這種情況下,我們就可以直接回傳布爾運算式即可,而不需要再進行條件判斷,讓代碼不夠簡潔:
public boolean isOdd(int num) {
return num % 2 == 1;
}
3. 使用衛陳述句
在1中我們以一個反例講訴了三元表示不用改被亂用,這里我們就先通過if陳述句,來進行改寫,寫出第一版代碼:
public int getMaxDays(int year, int month) {
int result;
if (month == 2) {
result = isLeapYear(year) ? 29 : 28;
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
result = 30;
} else {
result = 31;
}
return result;
}
private boolean isLeapYear(int year) {
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) ;
}
我們為了實作單入口單出口原則,而讓多次判斷都有依賴,如果每個判斷條件記憶體在大量的陳述句的時候,更會顯示出這種撰寫方式的弊端,因此對于這種情況,我們通常會撰寫單入口多出口的代碼,讓簡便情況盡快得到判斷,每個判斷陳述句之間不必耦合:
public int getMaxDays(int year, int month) {
if (month == 2) {
return isLeapYear(year) ? 29 : 28;
}
if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
}
return 31;
}
private boolean isLeapYear(int year) {
return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
}
4. 使用arraycopy拷貝陣列
我們有時可能因為不能在原陣列上進行修改,需要對原陣列進行一份拷貝,然后寫出類似下面這樣的代碼:
int[] arr = {1, 2, 3, 4, 5};
int[] temp = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
temp[i] = arr[i];
}
不過我們可以通過使用系統自帶的arraycopy函式,讓代碼更易讀,效率也更高:
int[] arr = {1, 2, 3, 4, 5};
int[] temp = new int[arr.length];
System.arraycopy(arr, 0, temp, 0, arr.length);
5. 使用try ... with ...進行資源管理
當使用io流時,我們由于需要對資源進行管理,需要寫出類似下面的代碼,當多個資源需要管理的時候,不僅難以管理,我們還可能經常會忘記對資源的關閉:
FileInputStream fis = null;
try {
fis = new FileInputStream(new File(""));
fis.read();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
但是通過使用try ... with ...就可以寫出下面這樣簡便的代碼,我們不需要再擔心資源的管理問題:
try (FileInputStream fis = new FileInputStream(new File(""))) {
fis.read();
} catch (Exception e) {
e.printStackTrace();
}
6. 位運算小技巧
相信很多人都知道,位運算在很多情況下都能表現出更好地性能,在某些情況下也能夠簡化代碼,這里就講兩個小例子:
-
使用位移代替乘除法:
a << n // <=> a * 2^n a >> n // <=> a / 2^n -
使用位運算避免二分法中的加法溢位:
相信很多人都知道在二分查找中,以下代碼可能因為加法運算的溢位,導致無法得到正確的結果:
int mid = (left + right) / 2;如果使用下面這種方法就可以避免:
int mid = left + (right - left) / 2;但是通過使用無符號位移,我們就可以寫出下面這樣簡潔的代碼,而且也可以避免溢位:
int mid = (left + right) >>> 1; -
判斷兩號是否同號
如果不使用位運算,我們需要寫出下面這樣的代碼:
(a >= 0 && b >= 0) || (a < 0 && b < 0)但是如果使用
^的特性,我們就可以寫出下面這樣簡潔的代碼:(a ^ b) >= 0
7. 分割字串
很多時候,我們為了進行列印除錯,都需要對陣列的資料或者字串進行分割列印,例如將[1, 2, 3]或者"123"列印為1, 2, 3的格式,按照傳統的方式,我們需要寫出下面這樣的代碼:
int[] arr = {1, 2, 3};
StringBuilder sb = new StringBuilder(String.valueOf(arr[0]));
for (int i = 1; i < arr.length; i++) {
sb.append(", ").append(arr[i]);
}
// output: 1, 2, 3
System.out.println(sb);
String str = "123";
String[] split = Pattern.compile("").split(str);
StringBuilder sb = new StringBuilder(split[0]);
for (int i = 1; i < split.length; i++) {
sb.append(", ").append(split[i]);
}
// output: 1, 2, 3
System.out.println(sb);
但是通過使用Stream的特性,我們就能寫出下面這樣更加方便易讀的代碼(為了代碼的可讀性,我們通常會將鏈式呼叫拆成多行):
int[] arr = {1, 2, 3};
// output: 1, 2, 3
System.out.println(
IntStream.of(arr)
.mapToObj(String::valueOf)
.collect(Collectors.joining(", "))
);
String str = "123";
// output: 1, 2, 3
System.out.println(
Pattern.compile("")
.splitAsStream(str)
.collect(Collectors.joining(", "))
);
8. 使用系統方法列印陣列
我們通常需要列印陣列進行除錯,正如7中所說的那樣,但是我們通常只要能夠得出陣列的資料即可,而不在乎其形式,但是如果直接列印陣列,只會得到一個記憶體地址,不過我們其實可以通過呼叫Arrays.toString(arr),很容易就實作我們的需求:
int[] arr = {1, 2, 3};
// output: [1, 2, 3]
System.out.println(Arrays.toString(arr));
9. Stream實作計數器
有時,我們需要對陣列或者集合中的資料進行統計其次數,我們會寫出如下所示的代碼:
int[] arr = {1, 2, 3, 4, 5, 6};
Map<Integer, Integer> map = new HashMap<>();
for (int val : arr) {
map.put(val, map.getOrDefault(val, 0) + 1);
}
如果利用Stream,我們就能夠更加專注于我們的業務邏輯,也可加易讀:
int[] arr = {1, 2, 3, 4, 5, 6};
Map<Integer, Integer> map = IntStream.of(arr)
.boxed()
.collect(Collectors.toMap(k -> k, k -> 1, Integer::sum));
10. 使用Arrays.asList(arr)將物件陣列轉換為集合
有時我們需要為了將陣列轉換為集合,然后寫出類似下面的代碼:
String[] strs = new String[10];
List<String> list = new ArrayList<>();
for (String str : strs) {
list.add(str);
}
但是利用Array.asList(arr)就可以寫出下面這樣簡潔的代碼:
String[] strs = new String[10];
// Array.asList(arr)生成的結果集合無法進行資料的修改,因此需要使用 new ArrayList<>();
List<String> list = new ArrayList<>(Arrays.asList(strs));
或者使用Stream這樣進行轉換:
String[] strs = new String[10];
List<String> list = Stream.of(strs).collect(Collectors.toList());
以上就是關于Java的一些編程小技巧,希望能夠對你有些幫助,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/108583.html
標籤:其他
上一篇:java專案實訓ATM存款機
