5

我正在做一个 xml 解析并做一些replaceAll使用大量内存空间的字符串,如下图所示。

代码如下:

private final String getText() {
  // special handling for apostrophe encoding
  // site will expect both ' , ' and %27.
  // change %27 or 'or ' to '
  return _text.toString().trim().replaceAll("'", "'")
            .replaceAll("'", "'").replaceAll("%27", "'");
}

getText()方法经常被endElement()SAXParser 的方法调用。

任何人都可以建议如何更改此功能以使用更少的堆空间

![踪迹][1]

4

6 回答 6

7

使用replace()而不是replaceAll(). replaceAll()使用正则表达式,你不需要它们,而且它们是开销。

于 2012-11-28T19:04:08.663 回答
3

像这样使用正则表达式进行简单的字符串替换太昂贵了。我会像这样简单地构建一个 StringBuilder 实例:

StringBuilder sb = new StringBuilder();

while (not end of _text) {
   find next '&'
   if the next substring is in (' ') etc.
     append the prev portion of _text to sb
     append replacement char
     set the beginning of the chunk to the next char
}
return sb.toString();
于 2012-11-28T19:05:08.957 回答
3

由于_text已经是StringBuffer您可以使用的indexOf(String str)and replace(int start, int end, String str)。这样,您根本不会创建临时String对象。

使用如下函数:

private void replace(StringBuffer buff,String toReplace,String replaceTo){
 int start;
 while ((start=buff.indexOf(toReplace))>=0)
   buff.replace(start,start+toReplace.length(),replaceTo);
}

并为每个组合调用 you 中的函数getText(),例如:

String replaceTo=",";
replace(_text,"'",replaceTo);
replace(_text,"'",replaceTo);
replace(_text,"%27",replaceTo);
return _text.toString();
于 2012-11-28T19:09:42.880 回答
2

您可以一次性完成所有 3 次替换

text.replaceAll("('|&39;|%27)", "'");

它比 3 次连续替换效率高 3 倍,因为每次替换都可能创建一个新字符串

于 2012-11-28T19:56:56.207 回答
1

由于您在 SAX 中获取文本,因此它必须来自这里

characters(char[] ch, int start, int length) 

您必须将这些参数保存在字段中,并且在 endElement() 上您可以将替换为

    StringBuilder sb = new StringBuilder();
    for (int i = start; i < length; i++) {
               // %27
        if (ch[i] == '%' && length - i > 2 && ch[i + 1] == '2' && ch[i + 2] == '7') {
                         sb.append('\'');
            i += 2;
                // &apos;
                } else if (
                   ...
                // &#39;
                } else if (
                   ...
        } else {
            sb.append(ch[i]);
        }
    }
    String res = sb.toString();

代码很长但是效率很高,还可以加trimming

于 2012-11-28T20:22:49.910 回答
1

您的 replaceAll 方法在 a 上调​​用String,它是不可变的。因此,每次修改时都必须创建一个全新的字符串(在这种情况下为 3 次)。如果您使用 aStringBuilder代替,您的字符串将是可变的,并且每次替换某些内容时都不需要再次分配。

顺便说一句,在 StringBuilders 中没有您需要的“替换”,因此您必须indexOf反复使用才能找到有问题的字符串,并replace根据结果进行查找。修剪()在那里。

于 2012-11-28T19:06:03.230 回答