Java 替换字符串中的多个子字符串

Java 替换字符串中的多个子字符串,java,regex,replace,matcher,Java,Regex,Replace,Matcher,我想用替换来替换某些子字符串,两者都是在Hashmap中定义的。一个例子如下: import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { private static HashMap<String, String> conversionTable; public static void main

我想用替换来替换某些子字符串,两者都是在Hashmap中定义的。一个例子如下:

import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexTest {
    private static HashMap<String, String> conversionTable;

    public static void main(String[] args) {
        initConversionTable();
        System.out.println(convertNumbers("la1"));
        System.out.println(convertNumbers("la1, lb3"));
    }

    private static String convertNumbers(String text) {
        String regex = "([aub][1-3])";
        Matcher m = Pattern.compile(regex).matcher(text);
        while(m.find()) {
            text  = m.replaceAll(conversionTable.get(m.group()));
        }

        return text;
    }

    private static void initConversionTable() {
        conversionTable = new HashMap<>();
        conversionTable.put("a1", "A1");
        conversionTable.put("a2", "A2");
        conversionTable.put("a3", "A3");
        conversionTable.put("u1", "U1");
        conversionTable.put("u2", "U2");
        conversionTable.put("u3", "U3");
        conversionTable.put("b1", "B1");
        conversionTable.put("b2", "B2");
        conversionTable.put("b3", "B3");
    }
}
预期的结果应该是

lA1
lA1, lB3
但是

lA1
lA1, lA1
直到现在,我还没有成功地找到一个解决方案与匹配。有这样的解决办法吗?当然,我可以遍历HashMap的每个条目并进行替换,但我希望使用匹配器解决它,因为我担心对于非常长的HashMap和许多字符串,这可能会影响性能


多谢各位

问题是您使用了replaceAll方法,因此这将发生

步骤1:

la1
la1, lb3
将进入循环,因为m.Find()返回true。它将找到第一个模式“la1”。现在,您将从表“lA1”中获得转换,并替换所有出现的模式,即“lA1”和“lb3”。 然后,循环将不会再次迭代,因为输出已经完成

lA1
lA1, lA1

要解决此问题,您只需将一个事件替换为相应的值,否则您将用第一个替换所有事件。

谢谢您的解释,我现在清楚了问题所在。我已经用
text=text.replace(m.group(),conversionTable.get(m.group())替换了替换发生的行。但是为什么
text=m.replaceFirst(conversionTable.get(m.group())不工作,即结果为空?可能需要重置循环的匹配器以再次正确评估:我也看到了它并尝试了,但它不工作。进一步阅读应该可以解决这个问题,但我现在将坚持我的第一个解决方案,否则它会变得复杂。再次感谢:)正如公认答案中所解释的,问题是
replaceAll
第一次替换所有出现的正则表达式匹配,它将
find()
,这将阻止其他匹配和正确替换。但要解决此问题,请不要使用
replaceFirst
。相反,当我们希望一个匹配另一个动态确定的替换(如基于地图中键的值)时,使用适当的工具精确地处理此类场景。因此,请使用Matcher类中的
appendReplacement
appendTail
。我将您的问题作为问题的副本关闭,您可以在其中看到使用这些方法的解决方案之一。你也可以看看其他的例子,比如,
lA1
lA1, lA1