我今天看到了这段代码
if (translatedText.contains("â")) translatedText = translatedText.replace("â", "a");
if (translatedText.contains("ê")) translatedText = translatedText.replace("ê", "e");
...
有22条这样的线,我想知道在替换之前使用“ifs”有什么意义。我理解它的方式是有效的,我们每行读取两次字符串,而当没有什么可以替换的时候直接调用replace方法会产生相同的效果,当有什么要替换时会更快。
但这只是我猜它的运作方式。有人可以确认或纠正我吗?
还有第二个问题。我们正在替换每个元音和每个符号“á”,“à”,“â”和“ä”。我敢打赌,在Java中有更好的方法。有什么建议吗?
感谢。
答案 0 :(得分:7)
documentation并没有告诉我们replace
如果没有匹配的子字符串会做什么,但是查看Oracle版本中的当前实现(Java 8) ):
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
...如果你先检查一下,它看起来就像你避免了一些工作,特别是内存分配(匹配器)。
并不是说不可能有更好的方法来接近这22个替换,可能是通过使用一个带有字符类([âê]
等的正则表达式),编译一次正则表达式,然后在循环中使用单个匹配器,非常大致相似(灵感来自this answer):
// You can do this part once somewhere if you want to
Pattern regex = Pattern.compile("[âê]");
// Then:
StringBuffer resultString = new StringBuffer();
Matcher regexMatcher = regex.matcher(translatedText);
while (regexMatcher.find()) {
String match = regexMatch.group();
String replacement;
switch (match) {
// ...various cases setting `replacement`
}
regexMatcher.appendReplacement(resultString, replacement);
}
regexMatcher.appendTail(resultString);
translatedText = resultString.toString();
或者如果你想过早地对其进行微观优化(我的失败):
// You can do this part once somewhere if you want to
Pattern regex = Pattern.compile("[âê]");
// Then:
StringBuffer resultString = null;
Matcher regexMatcher = regex.matcher(translatedText);
while (regexMatcher.find()) {
if (resultString == null) {
resultString = new StringBuffer(translatedText.length() + 100);
}
String match = regexMatch.group();
String replacement;
switch (match) {
// ...various cases setting `replacement`
}
regexMatcher.appendReplacement(resultString, replacement);
}
if (resultString != null) {
regexMatcher.appendTail(resultString);
translatedText = resultString.toString();
}
答案 1 :(得分:3)
关于"性能":这可能真的取决于JVM版本;换句话说:取决于replace()
更改的实现,如果到位可以节省一些正则表达式匹配器成本;或不。
关于第二个问题:基本上你有很多重复的代码。解决这个问题的一种方法:
您可以定义一些静态最终字段,例如:
Map<String, String> replacements = new HashMap<>();
然后填写:
replacements.put("â", "a");
...
然后使用循环来替换当前代码,该循环迭代该映射的条目,使用每个键/值作为replace()调用的参数。
或者,如其他答案所示,您可以执行类似
的操作replacements.put("[áàâä]", "a");
然后再使用replaceAll()。
答案 2 :(得分:2)
您可以使用正则表达式将所有不需要的字符替换为您的字符
String s="sasaáàdaâadsasä";
System.out.println(s.replaceAll("[áàâä]", "a"));
输出
sasaaadaaadsasa
[]
表示匹配此中任何出现的字符,如果找到则替换
要替换多个字符,您可以将替换呼叫链接起来,只需避免if
条件
String s="sasaáàdaâadsêêêasä";
String str=s.replaceAll("[áàâä]", "a").replaceAll("[ê]", "e");
System.out.println(str);
<强>输出:强>
sasaaadaaadseeeasa
答案 3 :(得分:2)
如果您希望摆脱明显多余的if
语句而不会导致性能下降,那么快速解决方案是切换到使用replace(char, char)
:
translatedText = translatedText.replace('â', 'a');
translatedText = translatedText.replace('ê', 'e');
这完全避免了正则表达式,无论是显式的还是隐藏的,并且在我的Java 8中也避免了在没有替换的情况下创建新的String
。
是否有更好的方法取决于几个因素,包括味道。其他几个答案都有很好的想法。