Java 编译还是不编译模式?

Java 编译还是不编译模式?,java,regex,string,performance,Java,Regex,String,Performance,我在做一个脚本代码生成器。我创建了一个模板脚本文件,其中包含一些参数和占位符的占位符,在生成过程中应该用实际值替换这些占位符。在回路内执行更换。生成器的性能非常重要(目前在Java7上)。我的困境如下: 这样做: private final String PHOLDER_SECT = "#__PHOLD_SECT__#"; private final String PARAM_PID = "__param_pid"; private final String PARAM_NAME =

我在做一个脚本代码生成器。我创建了一个模板脚本文件,其中包含一些参数和占位符的占位符,在生成过程中应该用实际值替换这些占位符。在回路内执行更换。生成器的性能非常重要(目前在Java7上)。我的困境如下:

这样做:

private final String PHOLDER_SECT = "#__PHOLD_SECT__#";
private final String PARAM_PID    = "__param_pid";
private final String PARAM_NAME   = "__param_name";
private final String PARAM_DESC   = "__param_desc";
...
for (int i = 0; i < sectionCount; i++) {

    // do something here...
    masterTmpl[i] = masterTmpl[i].replace(PHOLDER_SECT, someSectionCode);
    // something else here...
    masterTmpl[i] = masterTmpl[i].replace(PARAM_DESC, desc)
                                 .replace(PARAM_NAME, name)
                                 .replace(PARAM_PID,  pid)
    ...
}
private final String PHOLDER_SECT=“#uu_PHOLD_SECT_u35;”;
私有最终字符串PARAM_PID=“u PARAM_PID”;
私有最终字符串PARAM_NAME=“_PARAM_NAME”;
私有最终字符串PARAM_DESC=“_PARAM_DESC”;
...
对于(int i=0;i
或者类似的东西(要点是所有占位符都是符合模式的):

private final Pattern regexSect=Pattern.compile(Pattern.LITERAL)(“#(PHOLD)SECT),Pattern.LITERAL);
私有最终模式regexPid=Pattern.compile(“\u参数\u pid”,Pattern.LITERAL);
私有最终模式regexName=Pattern.compile(“\u参数\u名称”,Pattern.LITERAL);
私有最终模式regexDesc=Pattern.compile(“_param_desc”,Pattern.LITERAL);
...
对于(int i=0;i

我知道我可以测量执行情况等等,但我有点希望找到一个答案来解释在这种特殊情况下模式编译的(非)重要性…

这段代码可能快得多,因为它可以在一次搜索中发现模式的出现(而不是每个模式一次);最重要的是,所有替换都在一个过程中完成,而不是要求每个模式一个过程。由于复制和内存开销,构建多个字符串有点昂贵-这只构建最后一行中一个完全替换的字符串

    public static String replaceMany(String input, 
            Map<String, String> replacements) {
        // build a composite pattern for all replacement keys
        StringBuilder sb = new StringBuilder();
        String prefix = "";
        for (String k : replacements.keySet()) {
            sb.append(prefix).append(Pattern.quote(k));
            prefix = "|";
        }
        Pattern p = Pattern.compile(sb.toString());
        // replace in single loop
        Matcher m = p.matcher(input);
        StringBuffer output = new StringBuffer();
        while (m.find()) {
            // inspired by http://stackoverflow.com/a/948381/15472
            m.appendReplacement(output, "");
            output.append(replacements.get(m.group(0)));
        }
        m.appendTail(output);
        return output.toString();
    }
publicstaticstringreplacemanny(字符串输入,
地图替换){
//为所有替换密钥构建复合模式
StringBuilder sb=新的StringBuilder();
字符串前缀=”;
for(字符串k:replacements.keySet()){
sb.append(前缀)。append(模式。引号(k));
前缀=“|”;
}
Pattern p=Pattern.compile(sb.toString());
//单回路更换
匹配器m=p.Matcher(输入);
StringBuffer输出=新的StringBuffer();
while(m.find()){
//灵感来自http://stackoverflow.com/a/948381/15472
m、 附件(输出“”);
output.append(replacements.get(m.group(0));
}
m、 追加尾(输出);
返回output.toString();
}

如果要更换很多不同的东西,我认为从性能角度来看,这两种选择都不是特别好。无论您以何种方式多次读取文件或字符串,都可能使用一些不同的工具来完成(尤其是对于大多数以
\uuu param\uu
开头的参数)。@Vlasec“不同的工具”让您想到了什么?占位符命名如何影响这一点,我不确定我是否遵循…?我自己没有遇到过类似的问题,但基本上,这是解析。可以使用Regexp,但是如果您按顺序读取文件,查找任何
\uuuuu param…
,使用一些outputstream返回结果,它的性能会更好。查找
“\uuu param\u pid | uuu param\u name | uuu param\u desc”
更快,每次找到它们时都用适当的值替换它们,而不是执行多个搜索和替换过程。一致的命名允许您搜索
“_参数([a-z]+)”
;在
while(m.find())
循环中,您可以在任何情况下应用合适的替换。请看下面我的答案。给定的代码,即使基于非常合理的假设,在实际替换值包含特殊字符(例如$and)时,使其工作起来似乎相当棘手,这正是我的情况。我要么不断得到“非法组引用”或“命名捕获组缺少尾随'}'”,或者类似的内容,但似乎无法回避这些问题…@这可能会变得更复杂,但通常,您只需要
sb.append(prefix).append(“”.append(k).append(“”).append(“”)
。使用
$
,应该没有问题。通过捕获组,它们会被重新编号,并且有一种方法可以实现。如果
\Q
没有相应的
\E
,它会断开。可能还有更多的问题,但它们都是可以解决的这可能值得再问一个问题,比如“如何组合包含…”的正则表达式@Less-fixed-我忘了引用替换项。这并没有那么复杂,因为人们已经找到了解决问题的方法
    public static String replaceMany(String input, 
            Map<String, String> replacements) {
        // build a composite pattern for all replacement keys
        StringBuilder sb = new StringBuilder();
        String prefix = "";
        for (String k : replacements.keySet()) {
            sb.append(prefix).append(Pattern.quote(k));
            prefix = "|";
        }
        Pattern p = Pattern.compile(sb.toString());
        // replace in single loop
        Matcher m = p.matcher(input);
        StringBuffer output = new StringBuffer();
        while (m.find()) {
            // inspired by http://stackoverflow.com/a/948381/15472
            m.appendReplacement(output, "");
            output.append(replacements.get(m.group(0)));
        }
        m.appendTail(output);
        return output.toString();
    }