在 Java 的 If 語句中設置多個“或”條件的格式
1. 概述
在使用if
語句時,我們可能需要使用邏輯運算符(例如 AND 或 OR)在其中包含多個條件。這可能不是一個乾淨的設計,並且會影響代碼的可讀性和認知複雜性。
在本教程中,我們將看到在 if 語句中格式化多個值條件的替代方法。
2. 我們可以避免If
語句嗎?
假設我們有一個電子商務平台,為特定月份出生的人設置折扣。我們來看一段代碼:
if (month == 10 || month == 11) {
// doSomething()
} else if(month == 4 || month == 5) {
// doSomething2()
} else {
// doSomething3()
}
這可能會導致一些代碼難以閱讀。此外,即使我們有良好的測試覆蓋率,代碼也可能很難維護,因為它迫使我們將執行特定操作的不同條件放在一起。
2.1.使用乾淨的代碼
我們可以應用模式來替換許多 if 語句。例如,我們可以將 if 的多個條件的邏輯移至類或枚舉中。在運行時,我們將根據客戶端輸入在界面之間進行切換。同樣,我們可以看一下策略模式。
這與格式並不嚴格相關,通常會導致重新思考邏輯。儘管如此,我們可以考慮改進我們的設計。
2.2.改進方法語法
不過,只要代碼可讀且易於維護,使用if / else
邏輯並沒有什麼問題。例如,讓我們考慮以下代碼片段:
if (month == 8 || month == 9) {
return doSomething();
} else {
return doSomethingElse();
}
第一步,我們可以避免使用else
部分:
if (month == 8 || month == 9) {
return doSomething();
}
return doSomethingElse();
另外,還可以改進其他一些代碼,例如,用java.time
包的 Enum 替換月份數字:
if (month == OCTOBER || month == NOVEMBER || month == DECEMBER) {
return doSomething();
}
// ...
這些都是簡單而有效的代碼改進。因此,在應用複雜模式之前,我們首先應該看看是否可以簡化代碼的可讀性。
我們還將了解如何使用函數式編程。在 Java 中,這從版本 8 開始適用於 lambda 表達式語法。
3. 測試圖例
按照電子商務折扣示例,我們將創建測試並檢查折扣月份中的值。例如,從十月到十二月。否則我們將斷言 false。我們將設置允許的月份之內或之外的隨機月份:
Month monthIn() {
return Month.of(rand.ints(10, 13)
.findFirst()
.orElse(10));
}
Month monthNotIn() {
return Month.of(rand.ints(1, 10)
.findFirst()
.orElse(1));
}
可能有多個if
條件,但為了簡單起見,我們假設只有一個if / else
語句。
4. 使用開關
使用if
邏輯的替代方法是switch
命令。讓我們看看如何在我們的示例中使用它:
boolean switchMonth(Month month) {
switch (month) {
case OCTOBER:
case NOVEMBER:
case DECEMBER:
return true;
default:
return false;
}
}
請注意,如果需要,它將向下移動並檢查所有有效月份。此外,我們可以使用 Java 12 中的新switch
語法來改進這一點:
return switch (month) {
case OCTOBER, NOVEMBER, DECEMBER -> true;
default -> false;
};
最後,我們可以做一些測試來驗證值是否在範圍內:
assertTrue(switchMonth(monthIn()));
assertFalse(switchMonth(monthNotIn()));
5. 使用集合
我們可以使用集合來對滿足if
條件的內容進行分組,並檢查某個值是否屬於它:
Set<Month> months = Set.of(OCTOBER, NOVEMBER, DECEMBER);
讓我們添加一些邏輯來查看該集合是否包含特定值:
boolean contains(Month month) {
if (months.contains(month)) {
return true;
}
return false;
}
同樣,我們可以添加一些單元測試:
assertTrue(contains(monthIn()));
assertFalse(contains(monthNotIn()));
6.使用函數式編程
我們可以使用函數式編程將if / else
邏輯轉換為函數。按照這種方法,我們將可以預測方法語法的用法。
6.1.簡單謂詞
我們仍然使用contains()
方法。不過,這次我們使用[Predicate](https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html)
將其設為 lambda 表達式:
Predicate<Month> collectionPredicate = this::contains;
我們現在確信Predicate
是不可變的,沒有中間變量。如果我們需要的話,它的結果是可預測的並且可以在其他情況下重用。
讓我們使用test()
方法來檢查一下:
assertTrue(collectionPredicate.test(monthIn()));
assertFalse(collectionPredicate.test(monthNotIn()));
6.2.謂詞鏈
我們可以鏈接多個Predicate
在or
條件中添加我們的邏輯:
Predicate<Month> orPredicate() {
Predicate<Month> predicate = x -> x == OCTOBER;
Predicate<Month> predicate1 = x -> x == NOVEMBER;
Predicate<Month> predicate2 = x -> x == DECEMBER;
return predicate.or(predicate1).or(predicate2);
}
然後我們可以將其插入if
:
boolean predicateWithIf(Month month) {
if (orPredicate().test(month)) {
return true;
}
return false;
}
讓我們通過測試來檢查一下這是否有效:
assertTrue(predicateWithIf(monthIn()));
assertFalse(predicateWithIf(monthNotIn()));
6.3.流中的謂詞
類似地,我們可以在流過濾器中使用Predicate
。同樣,過濾器中的 lambda 表達式將取代並增強if
邏輯。 if
最終會消失。這是函數式編程的優點,同時仍保持良好的性能和可讀性。
讓我們在解析月份的輸入列表時對此進行測試:
List<Month> monthList = List.of(monthIn(), monthIn(), monthNotIn());
monthList.stream()
.filter(this::contains)
.forEach(m -> assertThat(m, is(in(months))));
我們還可以使用*predicateWithIf()*代替contains().
如果 lambda 支持方法簽名,則它沒有任何限制。例如,它可以是static
方法。
七、結論
在本教程中,我們學習瞭如何提高if
語句中多個條件的可讀性。我們看到瞭如何使用switch
。此外,我們還了解瞭如何使用集合來檢查它是否包含值。最後,我們了解瞭如何採用使用 lambda 表達式的函數式方法。 Predicate
和Stream
不太容易出錯,並且會增強代碼的可讀性和可維護性。
與往常一樣,本文中提供的代碼可以在 GitHub 上獲取。