【问题标题】:Java String replaceAll Recursive behaviorJava String replaceAll 递归行为
【发布时间】:2018-07-10 03:25:32
【问题描述】:

昨天我正在处理定制的信件和备忘录。并且我已经制作了映射关键字,例如:[Dateofbirth]、[Email]、[Employee]、[Salary] 等,将在生成时替换。

示例:亲爱的 [Employee],您当前的薪水是 [Salary]。

预期输出:

输出:亲爱的约翰,你现在的薪水是 12000。

我正在使用replaceAll()方法这里是一个代码。

   String str = "dear [Employee], your Current Salary is [Salary].";
        Map<String,String> vals = new HashMap<String,String>();
        vals.put("[Employee]","John");
        vals.put("[Salary]","12000");
        for(String key:vals.keySet()){
            str=str.replaceAll(key,vals.get(key));
        }
        System.out.println(str);

但结果是:

dJohn1200012000 [JohnJohnJohnJohnJohnJohnJohnJohn], JohnJohnu12000 Cu1200012000Johnnt 1200012000John1200012000John is [1200012000John1200012000John].

我很困惑并用谷歌搜索并试图纠正它,之后我将replaceAll() 更改为replace()

EX: str=str.replace(key,vals.get(key));

现在它工作正常。问题是为什么全部替换正在做这种行为replaceAll() 的核心概念是什么以及何时使用replace() 何时使用replaceAll()。 谢谢

【问题讨论】:

    标签: java replace replaceall


    【解决方案1】:

    在解决您的问题之前,我希望您了解 Java API 的 String#format。这样你就可以简单地写

    String formattedString = String.format("dear %s, your Current Salary is %.2f", "John", 12000.45);
    System.out.println(formattedString);
    

    如果您在不可避免的情况下自己这样做,replaceAll 会将第一个参数视为正则表达式,而不是要替换的普通字符串。

    来自 replaceAll 的文档。

    用给定的替换替换此字符串中与给定正则表达式匹配的每个子字符串。

    由于您的参数由[]组成,并且它们与其中的每个字符匹配。

    如果您摆脱 [] 并使用任何其他非元字符的特殊字符作为前 #,它将起作用。

        String str = "dear #Employee#, your Current Salary is #Salary#.";
        Map<String, String> vals = new HashMap<String, String>();
        vals.put("#Employee#", "John");
        vals.put("#Salary#", "12000");
        for (String key : vals.keySet()) {
            str = str.replaceAll(key, vals.get(key));
        }
        System.out.println(str);
    

    给你

    dear John, your Current Salary is 12000.
    

    或者像你最后说的那样直接使用replace()

    【讨论】:

    • +1,尽管值得一提的是,在许多情况下,命名占位符优于编号或未命名的位置相关占位符,例如 %s - 例如旨在翻译成多种语言的消息。
    【解决方案2】:

    让我们看一下replace 和replaceAll 方法的javadocs。转到 javadocs

    替换

    public String replace(CharSequence target, CharSequence replacement)
    

    替换此字符串中与文字目标匹配的每个子字符串 具有指定文字替换序列的序列。这 替换从字符串的开头到结尾进行,对于 例如,将字符串“aaa”中的“aa”替换为“b”将导致 “ba”而不是“ab”。

    所以简单来说,它用替换词替换所有目标词。

    全部替换

    public String replaceAll(String regex, String replacement)
    

    替换此字符串中与给定正则匹配的每个子字符串 具有给定替换的表达式。

    要了解给定的行为,了解正则表达式的工作原理很重要。正则表达式是一个独立的世界,但是,我们可以在这里讨论给定的正则表达式。

    方括号将一组字符组合在一起。调用该集合中的任何字符时都会匹配。

    例如:[abc] 将匹配所有的 a、b 和 c。由于replaceAll 使用正则表达式匹配,它会将a、b 和c 全部替换为替换字符串。

    【讨论】:

      【解决方案3】:

      replaceAll() 使用 regular expression 匹配。
      replace() 使用纯文本匹配。

      正则表达式[Employee] 是一个character class,它匹配Employe 的任何单个字符。

      【讨论】:

        【解决方案4】:

        replaceAll 将第一个参数视为正则表达式。因此,您需要转义正则表达式特定字符,在您的情况下是 [ 和 ]。它们表示一组字符,因此 replaceAll 匹配该集中的每个字符并替换为您提供的值。试试这个来获得你想要的输出 -

        vals.put("\\[Employee\\]","John");
        vals.put("\\[Salary\\]","12000");
        

        这里我们已经对特殊符号 [ 和 ] 进行了转义,因此它不再将其视为一个集合。

        工作计划 - https://www.ideone.com/2hCbIM

        【讨论】:

        • 更好,只是避免使用 char '[' 并使用其他东西而不是转义 1000 次。
        • 我同意,但 OP 想使用那个字符。
        【解决方案5】:

        ReplaceAll 编译正则表达式并应用于字符串。在这种情况下,由于您的 Key 具有 '[' ,它将匹配其中存在的任何字符。因此,对于每次出现,它都替换为值

        【讨论】:

          【解决方案6】:

          replaceAll() 需要 正则表达式,但 replace() 需要准确的字符串(字符序列)。正则表达式需要对其特殊字符进行转义。所以当需要简单替换字符串时使用replace()方法,当需要匹配正则表达式并需要替换时,使用replaceAll()。

          【讨论】:

            【解决方案7】:

            This link 可能有助于您理解它。 基本上,唯一的区别是replaceAll 替换所有与作为参数提供的regex 匹配的字符串,replace() 替换基于chars

            【讨论】:

              猜你喜欢
              • 2011-07-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-11-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多