利用Idea重構功能及Java8語法特性——優化深層嵌套代碼
當遇到深層嵌套代碼,如for,if,lambda表達式或內部類及這些代碼的組合,這時我們可以通過Java 8的語法特性來進行優化。
下面的代碼是一個嵌套循環的示例。
複製代碼
public MappedField getMappedField(final String storedName) {
for (final MappedField mf : persistenceFields) {
for (final String n : mf.getLoadNames()) {
if (storedName.equals(n)) {
return mf;
}
}
}
return null;
}
複製代碼
重構1:
嵌套的for/if語句通暢可以通過Java 8中的stream來替代。
Optional found = persistenceFields.stream()
.flatMap(mappedField -> mappedField.getLoadNames().stream())
.filter(storedName::equals)
.findFirst();
上述重構代碼會返回Optional,但筆者希望返回mappedField對象,再次改造後的代碼如下。
複製代碼
persistenceFields.stream()
.filter(mappedField -> {
for (String name : mappedField.getLoadNames()) {
if (storedName.equals(name)) {
return true;
}
}
return false;
}
)
.findFirst()
複製代碼
重構2: 進行更好的封裝
重構1還存在一些問題,我們需要了解mappedField的結構,並通過循環遍歷其所有name來找到匹配的name。根據迪米特法則(Law of Demeter ),及命令-不要去詢問法則(Tell, Don’t Ask), 下面代碼應該由MappedField對象來提供對應的方法來判斷,而不是由調用者去了解MappedField結構後去寫邏輯進行判斷。
for (final MappedField mf : persistenceFields) {
if (mf.hasName(storedName)) {
return mf;
}
}
因此將上述代碼提取爲MappedField類中獨立的方法,並命名爲hasName。如果使用的IDE 是IDEA則可以通過refractor中的extract功能完成提取。
最後調用hasName方法來替代循環判斷邏輯。
接着通過Idea的refractor 中的move功能將代碼移動到目標類位置。
接着通過stream來重構hasName方法,hasName方法變更爲下面的形式。
public Boolean hasName(String storedName) {
return getLoadNames().stream()
.anyMatch(storedName::equals);
}
經過上述步驟最終重構後的代碼爲。
public MappedField getMappedField(final String storedName) {
return persistenceFields.stream()
.filter(mf -> mf.hasName(storedName))
.findFirst()
.orElse(null);
}
如需要返回Optional包裝的對象則需要去掉orElse。
public Optional getMappedField(final String storedName) {
return persistenceFields.stream()
.filter(mf -> mf.hasName(storedName))
.findFirst();
}
總結
這類代碼特徵通常爲:
存在深層的循環或條件判斷嵌套。
需要通過多個getter方法來訪問對象內部數據。
重構方法:
考慮tell don’t ask原則,提供專用的方法供外部調用訪問數據,而不是通過使用者經過多次訪問去獲取對象數據。並通過stream提供的操作來完成重構。
原文地址https://www.cnblogs.com/Java-no-1/p/11305245.html