Java8 String ReplaceAll 改变了行为

标签 java regex string replaceall

我有这个text = "$i $index" 和这张 map :

Map<String, String> vars = new HashMap<String, String>();

        vars.put("i","index0");
        vars.put("index","counter0"); 

目标是用相对值替换所有键。
在此测试中,replaceAll 方法中使用的正则表达式是串联的结果

            firstTest();
            // first test results:
            // java 7: index0  counter0
            // java 8: index0  index0ndex

这里,replaceAll方法中使用的正则表达式是一个完整的字符串

            secondTest();
            // second test resuls:
            // java 7: index0  index0ndex
            // java 8: index0  index0ndex

在最后,我将 Pattern.quote 方法与连接的字符串和相同的字符串进行比较

            thirdTest();
            // third test results:
            // java 7: first: \Q$index\E second: \Q$index\E are equals: true
            // java 8: first: \Q$index\E second: \Q$index\E are equals: true

第一个测试代码:

private static void firstTest() {
    Map<String, String> vars = new HashMap<String, String>();

    vars.put("i","index0");
    vars.put("index","counter0");

    String text = "$i  $index";

    for (Entry<String, String> var : vars.entrySet())
        text = text.replaceAll(Pattern.quote("$"+var.getKey()), var.getValue());

    System.out.println(text);
}

第二个测试代码:

private static void secondTest() {
    Map<String, String> vars = new HashMap<String, String>();

    vars.put("$i","index0");
    vars.put("$index","counter0");

    String text = "$i  $index";

    for (Entry<String, String> var : vars.entrySet())
        text = text.replaceAll(Pattern.quote(var.getKey()), var.getValue());

    System.out.println(text);
}

第三个测试代码:

private static void thirdTest() {
    Map<String, String> vars = new HashMap<String, String>();
    vars.put("index","counter0");

    String firstQuote = Pattern.quote("$"+vars.keySet().toArray()[0]);
    String secondQuote = Pattern.quote("$index");

    System.out.println("first: " + firstQuote + " second: " + secondQuote 
                     + " are equals: " + firstQuote.equals(secondQuote));

}

有人可以解释一下为什么我会得到如此不同的结果吗?

最佳答案

输出的变化将由迭代顺序引起。

在迭代变量时,如果您首先获得 $i,则在文本字符串中,$i$index 中的 $i 都会被替换。在第二次迭代中,不会替换任何内容,因为它在字符串中没有找到任何“$index”。

如果您可以调试代码,您就可以找到答案。要按某种排序顺序获取值,请使用 LinkedHashMap(按插入顺序保存)或 TreeMap、sortedMap(由您设计的自定义顺序)

java.util.HashMap 是无序的;您不能也不应该假设任何超出此范围的事情。

此类不保证映射的顺序;特别是,它不保证顺序随着时间的推移保持不变。

java.util.LinkedHashMap 使用插入顺序。

此实现与 HashMap 的不同之处在于,它维护一个贯穿其所有条目的双向链表。该链表定义了迭代顺序,通常是将键插入映射的顺序(插入顺序)。

java.util.TreeMap 是一个 SortedMap,使用自然或自定义的键排序。

映射根据其键的自然顺序进行排序,或者通过映射创建时提供的比较器进行排序,具体取决于使用的构造函数。

关于Java8 String ReplaceAll 改变了行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29915842/

相关文章:

c# - 将双引号内联附加到字符串生成器时出现问题

python - 在 Python 中使用 RegEx 的函数解析器

regex - Sed正则表达式和子字符串取反

algorithm - 子串算法建议

java - 正则表达式索引 0 它是如何工作的

javascript - 如何用正则表达式解析svg `viewBox`属性?

python - 获取最长字符串长度的函数

java - SpringBoot & 嵌入式Tomcat : Unpack executable war on server

java - 将 CSS 文件附加到 Tomcat 中的 Java Servlet

java - Android 文件未复制到 SD 卡