String.substring()的性能与手动查找到复制的char []数组相比如何?

时间:2015-10-25 18:37:59

标签: string performance java-7

我正在研究一个连续扫描大量相对较短的字符串的函数,并从中生成大量的子字符串。该功能将用于高容量字符串处理系统。我更喜欢首先优化内存,CPU优先,因为我遇到的内存多于系统上的CPU压力。在这种情况下,性能如何比较:

//Java-ish PseudoCode
functionParent(List<String> strings) {
  StringBuilder result;
  for(String s : strings) {
    result.appendAll(functionA(s));
  }
}


functionA(String arg1) {
  results.add(arg1.substring(i, i + length)); //hotspot here
}

//Java-ish PseudoCode
functionParent(List<String> strings) {
  StringBuilder result;
  for(String s : strings) {
    result.appendAll(functionB(s.toCharArray()));
  }
}

functionB(char[] arg1) {
  results.add(new String(arg1,i, length)); //hotspot here
}

到目前为止,从我的测试中可以看出,内存方面它是一个清洗(char []分配可忽略不计并且不影响GC,两者都创建相同数量的新字符串/ substring()内存-leak在前一段时间被修复了),并且由于对子串的不断查找,因此CPU []版本获胜。这听起来不对吗?我在分析中遗漏了什么吗?

有关解决方案的说明 根据下面的答案,functionB似乎是最快的。还要注意在functionParent中有一个StringBuilder - 而StringBuilder有一个1append(char [],index,length)`function

2 个答案:

答案 0 :(得分:2)

List.map - 除了绑定检查之外,还可以通过调用String.substring来完成 - 除非结果是整个原始字符串,在这种情况下它只返回原始字符串。

所以我会使用你的第二个/“new String(value, beginIndex, subLen)”例子。

答案 1 :(得分:1)

如果您在String次操作中遇到大量substringappend类似操作的内存压力,您应该了解CharSequence抽象。许多API已经准备好使用这些API代替String

由于String本身实现了CharSequence,您可以将方法更改为接受CharSequence输入而不是String而不更改其有用性。 subSequence的{​​{1}}实现与String的执行方式相同,因此会复制内容,但您可以创建子序列而不使用CharBuffer.wrap(string, start, end)进行复制。

如上所述,大多数操作支持substring输入,最明显的是用于您的用例

请注意,char[]也会实现StringBuilder,因此可以在不需要创建中间CharSequence副本的情况下实现操作的往返。