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

blu*_*lds 5 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
}
Run Code Online (Sandbox Code Playgroud)

和:

//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
}
Run Code Online (Sandbox Code Playgroud)

据我到目前为止的测试来看,内存方面这是一次清洗(char[] 分配可以忽略不计并且不会影响 GC,两者都会创建相同数量的新字符串/ substring() 内存泄漏不久前已修复),并且由于不断查找子字符串,因此 char[] 版本在 CPU 方面获胜。这听起来正确吗?我的分析中是否遗漏了任何内容?


根据下面的答案,解决方案的注释 functionB似乎是最快的。另请注意, functionParent 中有一个 StringBuilder - 并且 StringBuilder 有一个 1append(char[], index, length)` 函数

Hol*_*ger 2

如果您因String包含大量类似操作的操作而面临substring内存压力append,那么您应该意识到这种CharSequence抽象。许多 API 已经准备好使用这些来代替String.

\n\n

由于String它本身实现了CharSequence,您可以更改您的方法来接受CharSequence输入,而不是String不改变它们的有用性。subSequencewill的实现Stringsubstring,因此复制内容,但您可以创建一个子序列而不使用复制CharBuffer.wrap(string, start, end)

\n\n

如前所述,大多数操作都支持CharSequence输入,尤其是对于您的用例

\n\n\n\n

请注意,StringBuilder还实现了CharSequence,因此允许您的操作往返,而无需创建中间String副本。

\n