我们正在使用Java SAX解析非常大的XML文件。我们的characters
实现如下:
@Override
public void characters(char ch[], int start, int length) throws SAXException {
String value = String.copyValueOf(ch, start, length);
...
}
(SAX传递的ch[]
数组往往很长)
但是我们最近遇到了一些性能问题,并且分析器向我们展示了超过20%的CPU使用率高于String.copyValueOf
的调用(在引擎盖下调用了new String(ch,start,length)
)。
是否有更有效的方法从字符数组中获取字符串,开始索引和长度比String.copyValueOf(ch, start, length)
或new String(ch,start,length)
?
答案 0 :(得分:4)
好问题,但我确定,答案是不。
这是因为任何String
对象构造都使用数组复制方法。它不能直接在存在的数组上构造,因为String
对象必须是不可变的,并且它的内部字符串数组表示是从外部变化封装的。
此外,在您的情况下,您处理某些数组的片段。无论如何都不可能在另一个数组的片段上构建String
对象。
答案 1 :(得分:1)
如@Andremoniy所述,如果你想使用一个String对象,就必须创建它并将内容复制到它中。
加速解析器的唯一可能性是将新构建的字符串对象的数量减少到最小。
我想,你的xml结构中的每个元素都包含起始和结束标记之间的原始数据。
因此,如果您在感兴趣的数据元素内,我建议只创建字符串。此外,我建议以某种方式限制可能的元素。例如,通过hierarchie-level或parent元素来减少stringcompaisons的数量。但这取决于xml结构。
protected boolean readChars = false;
protected int level = -1;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
++level;
if (level == 4) {
if (qName.equalsIgnoreCase("TextElement")) {
readChars = true;
}
}
}
@Override
public void characters(char ch[], int start, int length) throws SAXException {
if (readChars) {
String value = String.copyValueOf(ch, start, length);
...
readChars = false;
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
--level;
}
答案 2 :(得分:1)
可能同时,characters
可能在一个标记内被多次调用,在元素级别持有 StringBuilder 可能是合适的。这样做System.arrayCopy
。