【问题标题】:Improve code to replaceAll String改进代码以替换所有字符串
【发布时间】:2014-10-15 11:05:23
【问题描述】:

是否有另一种方法可以更有效地执行大量“replaceAll”,使用尽可能少的内存?

 public static String cleanWordTags(String source) {

    String copy = source;

    copy = copy.replaceAll("<P style=\"M[^>]*>", "<P>");
    copy = copy.replaceAll("<p style=\"M[^>]*>", "<p>");
    copy = copy.replaceAll("<p style=\"T[^>]*>", "<p>");

    copy = copy.replaceAll("<b style=[^>]*>", "<b>");

    copy = copy.replaceAll("<span class=\"M[^>]*>", "<span>");
    copy = copy.replaceAll("<span style='m[^>]*>", "<span>");
    copy = copy.replaceAll("<span style=\"f[^>]*>", "<span>");
    copy = copy.replaceAll("<span lang[^>]*>", "<span>");
    copy = copy.replaceAll("<span style=\"color[^>]*>", "<span>");
    copy = copy.replaceAll("<span style=\"m[^>]*>", "<span>");
    copy = copy.replaceAll("<span style=\"line[^>]*>", "<span>");
    copy = copy.replaceAll("<span style=\"L[^>]*>", "<span>");
    copy = copy.replaceAll("<span style=\"T[^>]*>", "<span>");
    copy = copy.replaceAll("<span style=\"t[^>]*>", "<span>");

    copy = copy.replaceAll("<br [^>]*>", "<br/>");

    copy = copy.replaceAll("<i style=[^>]*>", "");
    copy = copy.replaceAll("</i>", "");

    copy = copy.replaceAll("<st1:personname[^>]*>", "");
    copy = copy.replaceAll("</st1:personname>", "");

    copy = copy.replaceAll("<st1:metricconverter[^>]*>", "");
    copy = copy.replaceAll("</st1:metricconverter>", "");

    copy = copy.replaceAll("<br[^>]*>", "<br/>");

    copy = copy.replaceAll("<\\W\\Wendif\\W\\W\\W>", "");

    copy = copy.replaceAll("<![^>]*>", "");


    copy = copy.replaceAll("<[vowm]:[^>]*>", "");
    copy = copy.replaceAll("</[vowm]:[^>]*>", ""); //&

    copy = copy.replaceAll("&(amp|lt|gt);", "");
    copy = copy.replaceAll("&nbsp;", "");

    copy = copy.replaceAll("<img width[^>]*>", "");
    copy = copy.replaceAll("<img src=\"file:[^>]*>", "");


    return copy;
}

我发现我可以使用 StringUtils.replace 代替 replaceAll,但这仅适用于没有正则表达式的字符串。

谢谢!!!

新:

我尝试了下一个与 cmets 相关的代码,但替换相同的字符串需要 5 倍的时间:

 public static String cleanWordTags(String source) {
        String copy = source;

        long t0 = System.currentTimeMillis();

        String regex = "";

        regex += "(align=\"left\")";
        regex += "|(<mce:style>)";
        regex += "|(<i>)";
        regex += "|(<i style=[^>]*>)";
        regex += "|(</i>)";
        regex += "|(<st1:personname[^>]*>)";
        regex += "|(</st1:personname>)";
        regex += "|(<st1:metricconverter[^>]*>)";
        regex += "|(</st1:metricconverter>)";
        regex += "|(<\\W\\Wendif\\W\\W\\W>)";
        regex += "|(<![^>]*>)";
        regex += "|(<[vowm]:[^>]*>)";
        regex += "|(</[vowm]:[^>]*>)";
        regex += "|(&(amp|lt|gt);)";
        regex += "|(&nbsp;)";

        regex += "|(<img width[^>]*>)";
        regex += "|(<img src=\"file:[^>]*>)";

        Pattern p = Pattern.compile(regex);
        copy = p.matcher(copy.toUpperCase()).replaceAll("");

        regex = "";
        regex += "(<span style=\"t[^>]*>)";
        regex += "|(<span style=\"T[^>]*>)";
        regex += "|(<span style=\"L[^>]*>)";
        regex += "|(<span style=\"line[^>]*>)";
        regex += "|(<span style=\"m[^>]*>)";
        regex += "|(<span style=\"color[^>]*>)";
        regex += "|(<span lang[^>]*>)";
        regex += "|(<span style=\"f[^>]*>)";
        regex += "|(<span style='m[^>]*>)";
        regex += "|(<span class=\"M[^>]*>)";

        p = Pattern.compile(regex);
        copy = p.matcher(copy.toUpperCase()).replaceAll("");

        copy = copy.replaceAll("<br[^>]*>", "<br/>");

        //Sustituir
        //        copy = copy.replaceAll("<p class=[^>]*>", "<p>");
        //  copy = copy.replaceAll("<p align=[^>]*>", "<p>");
        copy = copy.replaceAll("<P style=\"M[^>]*>", "<P>");
        copy = copy.replaceAll("<p style=\"M[^>]*>", "<p>");
        copy = copy.replaceAll("<p style=\"T[^>]*>", "<p>");
        copy = copy.replaceAll("<b style=[^>]*>", "<b>");

        System.out.println(System.currentTimeMillis() - t0);

        return copy;
    }

【问题讨论】:

  • 为什么不使用 HTML 解析器之类的?正则表达式 + HTML == 坏主意。
  • 问题是我有一个tinymce,人们使用组件的按钮书写或者简单地从单词中复制粘贴,然后将结果用于生成文档,所以我需要控制我自己的标签。
  • 我没有解析,我正在删除标签:P
  • 您主要关心的是内存消耗还是时间消耗?你的琴弦有多长?

标签: java string performance replace replaceall


【解决方案1】:

您是否已经看过 streamflyer(请参阅:https://code.google.com/p/streamflyer/),虽然我不能说明性能,但他们声明:“修改流中的字符- 应用正则表达式,修复 XML 文档,随心所欲”

此外还有 streamflyer-regex-fast(参见:https://code.google.com/p/streamflyer-regex-fast/),它“提供了一种比 streamflyer 使用的算法更快的算法来匹配字符流上的正则表达式”

因此,如果您的数据为 Reader,例如作为StringReader,您可以轻松地将首页中的示例应用到您的代码中,如下所示:

Reader reader = new StringReader("source <p style=\"Memphis\">");
FastRegexModifier modifier = new FastRegexModifier("<P style=\"M[^>]*>", Pattern.CASE_INSENSITIVE, "<P>");
ModifyingReader modifyingReader = new ModifyingReader(reader, modifier);
String result = IOUtils.toString(modifyingReader);

这样做的好处是您可以使用CASE_INSENSITIVE 标志,这可能会减少您需要定义的规则数量。但请注意:这也可能会影响性能,因此您应该评估这两种可能性。

如果此解决方案有助于提高您的表现,请反馈。

【讨论】:

    【解决方案2】:

    即使您想使用正则表达式,这种方式也非常低效,因为您一次又一次地搜索整个字符串(并产生大量垃圾)。正确的方法是在类似于this one 的循环中使用Matcher 进行迭代。

    只需让 Matcher 匹配所有可能感兴趣的内容并根据它找到的内容进行分支。您的模式可能类似于

    (?:<(p|b|span|br|i|st1:personname|st1:metricconverter|\\W\\Wendif\\W\\W\\W|!|vowm:|img))[^>]+>)|&(amp|lt|gt|nbsp);
    

    它比你想要的更多,但在这种情况下你可以将替换设置为$0。它只需要一次通过整个字符串。您可能需要进行两次传递以使其更简单。

    【讨论】:

      【解决方案3】:

      最后我找到的唯一解决方案是将所有“replaceAll”替换为“replace”而不使用正则表达式,并尝试泛化正则表达式。

      非常感谢!!!

      【讨论】:

        猜你喜欢
        • 2021-07-14
        • 1970-01-01
        • 2022-01-14
        • 1970-01-01
        • 2016-04-12
        • 2019-06-16
        • 2017-12-09
        • 2012-06-26
        • 2023-03-11
        相关资源
        最近更新 更多