首页 > 解决方案 > 字符串替换方法是否使用正则表达式?

问题描述

直到现在,我都认为该replace方法不使用正则表达式;然而在String类里面,我看到有一个 Pattern 编译就像在replaceAll

我看到的唯一区别是该compile方法LITERAL设置了一个标志。

public String replace(CharSequence target, CharSequence replacement) {
        return Pattern.compile(target.toString(), Pattern.LITERAL)
                       .matcher(this)
                       .replaceAll(Matcher.quoteReplacement(replacement.toString()));
}

所以我的问题是:

如果我正在使用replacefor 循环中的方法进行密集的字符串替换(例如,数千个),我应该缓存模式并使用它的匹配器来替换吗?

目前我使用

private static final Pattern patternContainsC = Pattern.compile("(~C)|(\\[C])");

加快一些使用类replaceAll方法的循环String

标签: java

解决方案


  1. String.replace(CharSequence target, CharSequence replacement)在较旧的JDK中使用正则表达式:
  1. 从 Java 9 开始,String.replace不编译target成正则表达式:
   /**
     * Replaces each substring of this string that matches the literal target
     * sequence with the specified literal replacement sequence. The
     * replacement proceeds from the beginning of the string to the end, for
     * example, replacing "aa" with "b" in the string "aaa" will result in
     * "ba" rather than "ab".
     *
     * @param  target The sequence of char values to be replaced
     * @param  replacement The replacement sequence of char values
     * @return  The resulting string
     * @since 1.5
     */
    public String replace(CharSequence target, CharSequence replacement) {
        String tgtStr = target.toString();
        String replStr = replacement.toString();
        int j = indexOf(tgtStr);
        if (j < 0) {
            return this;
        }
        int tgtLen = tgtStr.length();
        int tgtLen1 = Math.max(tgtLen, 1);
        int thisLen = length();

        int newLenHint = thisLen - tgtLen + replStr.length();
        if (newLenHint < 0) {
            throw new OutOfMemoryError();
        }
        StringBuilder sb = new StringBuilder(newLenHint);
        int i = 0;
        do {
            sb.append(this, i, j).append(replStr);
            i = j + tgtLen;
        } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
        return sb.append(this, i, thisLen).toString();
    }
  1. 方法String.replaceAll从目标编译它自己的模式。

那么,如果将同一个字符串模式应用于多个字符串,那么缓存该模式并使用Matcher'replaceAll方法是合理的。

// this pattern checks if string contains '~C' or '[C]'
private static final Pattern patternContainsC = Pattern.compile("(~C)|(\\[C])");

public static String replaceSpecialC(String src, String replacement) {
    if (null == src || src.isEmpty()) {
        return src;
    }
    return patternContainsC.matcher(src).replaceAll(replacement);
}

推荐阅读