天天看點

利用Idea重構功能及Java8文法特性——優化深層嵌套代碼

利用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);           

經過上述步驟最終重構後的代碼為。

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