簡體   English   中英

重構這個簡單方法的最有效方法是什么?

[英]What's the most effective way to refactor this simple method?

我實現了一個非常簡單的方法:

private String getProfileName(String path) {
    String testPath = null;
    for (int i = 0; i < path.length(); i++) {
       testPath = path.substring(0, i);
          if ( testPath.endsWith("1") || testPath.endsWith("2") || testPath.endsWith("3") || testPath.endsWith("4") || testPath.endsWith("5") || testPath.endsWith("6") || testPath.endsWith("7") || testPath.endsWith("8") || testPath.endsWith("9") ) {
            break;
          }
    }
    return testPath.substring(0, (testPath.length() - 1));
}

我不喜歡整個方法,因為我認為它比必要的更復雜,尤其是if條件。

所以我想到了一種重構這種方法的方法。 首先,我想到使用Regex來替換if條件,但對於這個簡單的情況,是不是正則表達式有點太多了?

任何其他想法如何重新審視這個?

將此模式與匹配器一起使用:

"^[^1-9]*"

示例代碼:

private String getProfileName(String path) {
    Pattern pattern = Pattern.compile("^[^1-9]*");
    Matcher matcher = pattern.matcher(path);
    matcher.find();
    return matcher.group();
}

我認為這比你的代碼更容易理解。 我花了幾分鍾來計算你的邏輯,我必須運行它才能確定。 我認為使用正則表達式很清楚代碼在做什么。 如果您希望可以只編譯一次正則表達式並通過將其移動到類的靜態成員來重用它。

正則表達式對Stack Overflow有很大的恥辱(主要來自試圖使用它們來解析HTML,電子郵件地址,URL以及各種其他令人討厭的正則表達式的不當使用的人)。 但是對於這種任務,正則表達式就好了。

您可能還想考慮為什么要省略0,如果這是個好主意。

礦:

private String getProfileName(String path) {

    return path.split("[1-9]")[0];
}

希望這會幫助你。

說明。 正如Mark Byers所說,數字上的Split(第一個版本,第二個版本忽略0),並返回結果數組的第一個元素。 但我認為如果第一個參數是一個數字(用jdk1.6.0_20測試),它不會失敗。 如果路徑中的所有字符都是數字(例如“2223”),則會失敗。 您可以使用此版本來避免錯誤:

private String getProfileName(String path) {

    String[] result = path.split("[1-9]");
    return result.length > 0 ? result[0] : "";
}

正如您將在String的split方法javadocs中 ,它接受一個參數(正則表達式),您可以使用以下方法之一:

return path.split("[1-9]")[0]; //if you want to avoid 0
return path.split("\\d")[0]; //if you don't

恕我直言:如果您正在尋求提高代碼可讀性,使用split方法比其他方法更好,

當然,你可以使用蠻力重構...但為什么不使用Apache Commons?

private String getProfileName(String path) {
    int index = StringUtils.indexOfAny(path, "123456789");
    if(index != -1) {
        return path.substring(0, index);
    }
    return path;
}

除了正則表達式:

private static String getProfileName(String path) {
    final int len = path.length();
    for (int i=0; i<len; ++i) {
       char c = path.charAt(i);
       if ('1' <= c && c <= '9') {
           return i==0 ? "" : path.substring(0, i-1); // Probably don't want that -1 !!
       }
    }
    return len==0 ? "" : path.substring(0, len-1);
}

或者,對於Single Entry,Single Exit粉絲:

private static String getProfileName(String path) {
    final int len = path.length();
    int i=0;
    while (i != len && !isProfileTerminator(path.charAt(i))) {
    //Or (!(i == len || isProfileTerminator(path.charAt(i)))) {
       ++i;
    }
    return i==0 ? "" : path.substring(0, i-1);
}
private static boolean isProfileTerminator(char c) {
    return '1' <= c && c <= '9');
}

原始代碼中存在問題,字符串為空或以1-9開頭。

  private String getProfileName(String path)
  {
    int i;
    for (i = 0; i < path.length() && !Character.isDigit(path.charAt(i)); i++);
    return path.substring(0, i);
  }

我會說與正則表達式一起去。 我想不出更簡單的重構方法。 我可能會想到復雜的方法,但我不認為你會想要那樣。

這是一個單行的正則表達式解決方案,非常簡單:

private String getProfileName(String path) {
    return path.replaceFirst("(?s)\\d.*", "");
}

Pattern.DOTALL模式下,模式為\\d.* ,作為嵌入式標志(?s) 這將匹配一個數字,以及它之后的所有內容。 我們想刪除這部分,所以我們用空字符串替換。

請注意, \\d包含0 ,因此如果真的是規范,則替換為[1-9]

參考

您可以創建一個這樣的方法放入if

private static boolean endsWith1to9(String a) {
        for(int i = 1; i <= 9; i++) {
            if(a.endsWith(String.valueOf(i))) {
                return true;
            }
        }
        return false;
    }

我覺得這樣的事情會起作用。 如果我錯了,有人會糾正我。

private String getProfileName(String path) {
    int i = 0;
    for(i = 0; i < path.length; ++i)
    {
        if(path.charAt(i) > '0' && path.charAt(i) <= '9') break;
    }
    return path.substring(0, i-1);
}

我的嘗試:

/**
 * Numeric Register Optimized Search with Null Pointer Handling.
 * -> No use of Regex (per requirement). :)
 * -> No use of Character.isDigit() (NOTE: includes characters other than [0-9].)
 * -> Catch and Avoid NullPointerExceptions (Oops... review other methods above.)
 * -> Reduce for(...; test ; ...) to while(test) by variable declaration and ++off use.
 * -> Include ANDed test to avoid break call.
 * -> Cache "path.length" in local variable (e.g. CPU register)
 * -> Cache "path.charAt(off)" in local variable (e.g. CPU register)
 * -> Replace String.endsWith(...) Method with char < char Register Method.
 * -> Reuse path argument to avoid another internal object reference.
 * -> Avoid call to substring if [1-9] not found in path.
 * -> Single Entry/Single Exit Happy. :)
 * @return path null if passed null, otherwise valid value.
 */
private String getProfileName(String path) {
    if (path != null) {
        int off = -1, len = path.length;
        final char one = '1', nine = '9';
        char c;
        while (++off < len && (c = path.charAt(off)) < one && c > nine);
        if (off < len) {
            path = path.substring(0, off);
        }
    }
    return (path);
}
干杯,loeJava

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM