Java 使用 StringBuilder 替换所有出现的字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3472663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:05:13  来源:igfitidea点击:

Replace all occurrences of a String using StringBuilder?

java

提问by meteoritepanama

Am I missing something, or does StringBuilder lack the same "replace all occurrences of a string A with string B" function that the normal String class does? The StringBuilder replace function isn't quite the same. Is there any way to this more efficiently without generating multiple Strings using the normal String class?

我是否遗漏了什么,或者 StringBuilder 是否缺少与普通 String 类相同的“用字符串 B 替换所有出现的字符串 A”功能?StringBuilder 替换函数并不完全相同。在不使用普通 String 类生成多个字符串的情况下,有没有更有效的方法?

回答by Jon Skeet

Well, you can write a loop:

好吧,你可以写一个循环:

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);
    }
}

Note that in some cases it may be faster to use lastIndexOf, working from the back. I suspect that's the case if you're replacing a long string with a short one - so when you get to the start, any replacements have less to copy. Anyway, this should give you a starting point.

请注意,在某些情况下lastIndexOf,从后面使用可能会更快。我怀疑如果您用短字符串替换长字符串,情况就是这种情况 - 因此,当您开始时,任何替换都没有什么可复制的。无论如何,这应该给你一个起点。

回答by Pierre

java.util.regex.Pattern.matcher(CharSequence s)can use a StringBuilder as an argument so you can find and replace each occurence of your pattern using start() and end() without calling builder.toString()

java.util.regex.Pattern.matcher(CharSequence s)可以使用 StringBuilder 作为参数,因此您可以使用 start() 和 end() 查找和替换模式的每个出现,而无需调用 builder.toString()

回答by Ron Romero

You could use Pattern/Matcher. From the Matcher javadocs:

您可以使用Pattern/ Matcher。来自 Matcher javadocs:

 Pattern p = Pattern.compile("cat");
 Matcher m = p.matcher("one cat two cats in the yard");
 StringBuffer sb = new StringBuffer();
 while (m.find()) {
     m.appendReplacement(sb, "dog");
 }
 m.appendTail(sb);
 System.out.println(sb.toString());

回答by Alfredo Osorio

Look at JavaDoc of replaceAllmethod of Stringclass:

查看String类的replaceAll方法的JavaDoc :

Replaces each substring of this string that matches the given regular expression with the given replacement. An invocation of this method of the form str.replaceAll(regex, repl) yields exactly the same result as the expression

java.util.regex.Pattern.compile(regex).matcher(str).replaceAll(repl)

用给定的替换替换此字符串中与给定正则表达式匹配的每个子字符串。以 str.replaceAll(regex, repl) 形式调用此方法会产生与表达式完全相同的结果

java.util.regex.Pattern.compile(regex).matcher(str).replaceAll(repl)

As you can see you can use Patternand Matcherto do that.

如您所见,您可以使用PatternMatcher来做到这一点。

回答by Anandan

Use the following:

使用以下内容:

/**
* 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);
    }
}

回答by user2995215

Even simple one is using the String ReplaceAll function itself. You can write it as

甚至简单的方法是使用 String ReplaceAll 函数本身。你可以把它写成

StringBuilder sb = new StringBuilder("Hi there, are you there?")
System.out.println(Pattern.compile("there").matcher(sb).replaceAll("niru"));

回答by Adam Gent

Here is an in place replaceAll that will modify the passed in StringBuilder. I thought that I would post this as I was looking to do replaceAll with out creating a new String.

这是一个适当的 replaceAll,它将修改 StringBuilder 中传递的内容。我想我会发布这个,因为我希望在不创建新字符串的情况下执行 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);
    }
}

I was shocked how simple the code to do this was (for some reason I thought changing the StringBuilder while using the matcher would throw of the group start/end but it does not).

我很震惊执行此操作的代码是多么简单(出于某种原因,我认为在使用匹配器时更改 StringBuilder 会抛出组开始/结束,但事实并非如此)。

This is probably faster than the other regex answers because the pattern is already compiled and your not creating a new String but I didn't do any benchmarking.

这可能比其他正则表达式答案更快,因为该模式已经编译并且您没有创建新的 String 但我没有进行任何基准测试。

回答by Paul Vargas

The class org.apache.commons.lang3.text.StrBuilderin Apache Commons Langallows replacements:

这个类org.apache.commons.lang3.text.StrBuilder的Apache Commons Lang中允许更换:

public StrBuilder replaceAll(String searchStr, String replaceStr)

* This does not receive a regular expression but a simple string.

*这不接收正则表达式,而是一个简单的字符串。

回答by fir99

@Adam: I think in your code snippet you should track the start position for m.find() because string replacement may change the offset after the last character matched.

@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();
    }
}

回答by ramesh

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();
    }