[英]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.