9

我们正在使用 Java SAX 来解析非常大的 XML 文件。我们的characters实现如下所示:

@Override
public void characters(char ch[], int start, int length) throws SAXException {
    String value = String.copyValueOf(ch, start, length);
    ...
}

ch[]SAX 传递的数组往往很长)

但是我们最近遇到了一些性能问题,分析器向我们显示超过 20% 的 CPU 使用率高于调用String.copyValueOfnew String(ch,start,length)在后台调用)。

有没有比String.copyValueOf(ch, start, length)or更有效的方法来从字符数组、起始索引和长度获取字符串new String(ch,start,length)

4

3 回答 3

4

好问题,但我敢肯定,答案是否定的。

这是因为任何String对象构造都使用数组复制方法。它不能直接在现有数组上构造,因为String对象必须是不可变的,并且它的内部字符串数组表示是从外部更改封装的。

此外,在您的情况下,您需要处理某个数组的片段。不可能以String任何方式在另一个数组的片段上构建对象。

于 2013-06-06T07:51:56.310 回答
2

正如@Andremoniy 所说,如果要使用 String 对象,则必须始终创建它并将内容复制到其中。

加速解析器的唯一可能性是将新构建的字符串对象的数量减少到最低限度。

我怀疑,您的 xml 结构中的每个元素都包含开始和结束标记之间的原始数据。

因此,我建议仅在您位于数据感兴趣的元素中时才创建字符串。此外,我建议以某种方式限制可能的元素。例如通过层次结构或父元素来减少字符串组合的数量。但这取决于 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;
}
于 2013-06-06T07:56:20.143 回答
1

可能结合在一起,characters可能会在一个标签内多次调用,在元素级别持有StringBuilder可能是合适的。这会做一个System.arrayCopy.

于 2013-06-06T08:17:33.697 回答