我是否缺少某些东西,或者StringBuilder是否缺少与普通String类相同的“用字符串B替换所有出现的字符串A”功能?StringBuilder的替换功能并不完全相同。有没有什么方法可以更有效地使用普通的String类生成多个String?
我是否缺少某些东西,或者StringBuilder是否缺少与普通String类相同的“用字符串B替换所有出现的字符串A”功能?StringBuilder的替换功能并不完全相同。有没有什么方法可以更有效地使用普通的String类生成多个String?
String.replaceAll正则表达式的事情?我不会担心在StringBuilder和之间进行转换的开销String。
Answers:
好了,您可以编写一个循环:
public static void replaceAll(StringBuilder builder, String from, String to)
{
int index = builder.indexOf(from);
while (index != -1)
{
builder.replace(index, index + from.length(), to);
index += to.length(); // Move to the end of the replacement
index = builder.indexOf(from, index);
}
}
请注意,在某些情况下lastIndexOf,从背面开始使用可能会更快。我怀疑是这样,如果要用短字符串替换长字符串-因此,从一开始,任何替换副本的复制量都很少。无论如何,这应该给您一个起点。
from和的to长度不同,此解决方案将在每次替换时移动缓冲区尾部。这对于发生很多替换的长缓冲区可能是非常无效的。罗恩·罗梅罗(Ron Romero)的答案没有这个缺点,但是涉及到单个正则表达式搜索。我猜想更快些取决于用例。
builder = builder.replace(builder.indexOf(from), builder.indexOf(from) + from.length(), to);
$。如果您根本不需要引用匹配的字符串,则只需通过即可运行替换文本Matcher.quoteReplacement(...)。所以m.appendReplacement(sb, Matcher.quoteReplacement(someText));
@Adam:我认为您应该在代码段中跟踪m.find()的起始位置,因为字符串替换可能会更改最后一个匹配的字符后的偏移量。
public static void replaceAll(StringBuilder sb, Pattern pattern, String replacement) {
Matcher m = pattern.matcher(sb);
int start = 0;
while (m.find(start)) {
sb.replace(m.start(), m.end(), replacement);
start = m.start() + replacement.length();
}
}
查看String类的replaceAll方法的JavaDoc :
用给定的替换项替换该字符串中与给定的正则表达式匹配的每个子字符串。以str.replaceAll(regex,repl)形式调用此方法,其结果与表达式完全相同
java.util.regex.Pattern.compile(regex).matcher(str).replaceAll(repl)
如您所见,您可以使用Pattern和Matcher来做到这一点。
这个类org.apache.commons.lang3.text.StrBuilder中的Apache Commons Lang中允许更换:
public StrBuilder replaceAll(String searchStr, String replaceStr)
*它不接收正则表达式,而是一个简单的字符串。
java.util.regex.Pattern.matcher(CharSequence s)可以使用StringBuilder作为参数,因此您可以使用start()和end()查找并替换模式中的每个匹配项,而无需调用builder.toString()
使用以下内容:
/**
* Utility method to replace the string from StringBuilder.
* @param sb the StringBuilder object.
* @param toReplace the String that should be replaced.
* @param replacement the String that has to be replaced by.
*
*/
public static void replaceString(StringBuilder sb,
String toReplace,
String replacement) {
int index = -1;
while ((index = sb.lastIndexOf(toReplace)) != -1) {
sb.replace(index, index + toReplace.length(), replacement);
}
}
是。String.replaceAll()方法非常简单:
package com.test;
public class Replace {
public static void main(String[] args) {
String input = "Hello World";
input = input.replaceAll("o", "0");
System.out.println(input);
}
}
输出:
Hell0 W0rld
如果您真的想使用它,StringBuilder.replace(int start, int end, String str)那么请转到:
public static void main(String args[]) {
StringBuilder sb = new StringBuilder("This is a new StringBuilder");
System.out.println("Before: " + sb);
String from = "new";
String to = "replaced";
sb = sb.replace(sb.indexOf(from), sb.indexOf(from) + from.length(), to);
System.out.println("After: " + sb);
}
输出:
Before: This is a new StringBuilder
After: This is a replaced StringBuilder
这是一个就地replaceAll,它将修改在StringBuilder中传递的内容。我以为我打算在不创建新String的情况下执行replaceAll时发布此消息。
public static void replaceAll(StringBuilder sb, Pattern pattern, String replacement) {
Matcher m = pattern.matcher(sb);
while(m.find()) {
sb.replace(m.start(), m.end(), replacement);
}
}
使我感到震惊的是,执行此操作的代码如此简单(出于某些原因,我认为在使用匹配器时更改StringBuilder会引发组开始/结束,但事实并非如此)。
这可能比其他正则表达式的答案要快,因为该模式已经编译,并且您没有创建新的String,但是我没有进行任何基准测试。
如何创建方法并String.replaceAll为您做:
public static void replaceAll(StringBuilder sb, String regex, String replacement)
{
String aux = sb.toString();
aux = aux.replaceAll(regex, replacement);
sb.setLength(0);
sb.append(aux);
}
public static String replaceCharsNew(String replaceStr,Map<String,String> replaceStrMap){
StringBuilder replaceStrBuilder = new StringBuilder(replaceStr);
Set<String> keys=replaceStrMap.keySet();
for(String invalidChar:keys){
int index = -1;
while((index=replaceStrBuilder.indexOf(invalidChar,index)) !=-1){
replaceStrBuilder.replace(index,index+invalidChar.length(),replaceStrMap.get(invalidChar));
}
}
return replaceStrBuilder.toString();
}
我找到了这个方法:Matcher.replaceAll(String replacement); 在java.util.regex.Matcher.java中,您可以看到更多信息:
/**
* Replaces every subsequence of the input sequence that matches the
* pattern with the given replacement string.
*
* <p> This method first resets this matcher. It then scans the input
* sequence looking for matches of the pattern. Characters that are not
* part of any match are appended directly to the result string; each match
* is replaced in the result by the replacement string. The replacement
* string may contain references to captured subsequences as in the {@link
* #appendReplacement appendReplacement} method.
*
* <p> Note that backslashes (<tt>\</tt>) and dollar signs (<tt>$</tt>) in
* the replacement string may cause the results to be different than if it
* were being treated as a literal replacement string. Dollar signs may be
* treated as references to captured subsequences as described above, and
* backslashes are used to escape literal characters in the replacement
* string.
*
* <p> Given the regular expression <tt>a*b</tt>, the input
* <tt>"aabfooaabfooabfoob"</tt>, and the replacement string
* <tt>"-"</tt>, an invocation of this method on a matcher for that
* expression would yield the string <tt>"-foo-foo-foo-"</tt>.
*
* <p> Invoking this method changes this matcher's state. If the matcher
* is to be used in further matching operations then it should first be
* reset. </p>
*
* @param replacement
* The replacement string
*
* @return The string constructed by replacing each matching subsequence
* by the replacement string, substituting captured subsequences
* as needed
*/
public String replaceAll(String replacement) {
reset();
StringBuffer buffer = new StringBuffer(input.length());
while (find()) {
appendReplacement(buffer, replacement);
}
return appendTail(buffer).toString();
}