Dan*_*Dan 36 java string performance
在Java中连接两个字符串的最快方法是什么?
即
String ccyPair = ccy1 + ccy2;
Run Code Online (Sandbox Code Playgroud)
我cyPair在a中使用它作为键HashMap,它在一个非常紧凑的循环中被调用来检索值.
当我描述然后这是瓶颈
java.lang.StringBuilder.append(StringBuilder.java:119)
java.lang.StringBuilder.(StringBuilder.java:93)
Run Code Online (Sandbox Code Playgroud)
Dun*_*gor 42
很多理论 - 一些练习的时间!
private final String s1 = new String("1234567890");
private final String s2 = new String("1234567890");
Run Code Online (Sandbox Code Playgroud)
在一台热身的64位热点上使用plain for 10,000,000循环,在Intel Mac OS上使用1.6.0_22.
例如
@Test public void testConcatenation() {
for (int i = 0; i < COUNT; i++) {
String s3 = s1 + s2;
}
}
Run Code Online (Sandbox Code Playgroud)
在循环中使用以下语句
String s3 = s1 + s2;
Run Code Online (Sandbox Code Playgroud)
1.33s
String s3 = new StringBuilder(s1).append(s2).toString();
Run Code Online (Sandbox Code Playgroud)
1.28秒
String s3 = new StringBuffer(s1).append(s2).toString();
Run Code Online (Sandbox Code Playgroud)
1.92s
String s3 = s1.concat(s2);
Run Code Online (Sandbox Code Playgroud)
0.70s
String s3 = "1234567890" + "1234567890";
Run Code Online (Sandbox Code Playgroud)
0.0S
所以concat是明显的胜利者,除非你有静态字符串,在这种情况下编译器将会照顾你.
Tho*_*sen 19
这些例程出现在基准测试中的原因是因为这就是编译器在封面下实现"+"的方式.
如果你真的需要连接字符串,你应该让编译器用"+"来实现它的魔力.如果你们都需要一个用于地图查找的键,那么一个包含适当equals和hashMap实现的字符串的键类可能是一个好主意,因为它避免了复制步骤.
sfo*_*dal 19
我相信答案可能已经确定,但我发帖分享代码.
简短的回答,如果您正在寻找纯粹的连接,那就是:String.concat(...)
输出:
ITERATION_LIMIT1: 1
ITERATION_LIMIT2: 10000000
s1: STRING1-1111111111111111111111
s2: STRING2-2222222222222222222222
iteration: 1
null: 1.7 nanos
s1.concat(s2): 106.1 nanos
s1 + s2: 251.7 nanos
new StringBuilder(s1).append(s2).toString(): 246.6 nanos
new StringBuffer(s1).append(s2).toString(): 404.7 nanos
String.format("%s%s", s1, s2): 3276.0 nanos
Tests complete
Run Code Online (Sandbox Code Playgroud)
示例代码:
package net.fosdal.scratch;
public class StringConcatenationPerformance {
private static final int ITERATION_LIMIT1 = 1;
private static final int ITERATION_LIMIT2 = 10000000;
public static void main(String[] args) {
String s1 = "STRING1-1111111111111111111111";
String s2 = "STRING2-2222222222222222222222";
String methodName;
long startNanos, durationNanos;
int iteration2;
System.out.println("ITERATION_LIMIT1: " + ITERATION_LIMIT1);
System.out.println("ITERATION_LIMIT2: " + ITERATION_LIMIT2);
System.out.println("s1: " + s1);
System.out.println("s2: " + s2);
int iteration1 = 0;
while (iteration1++ < ITERATION_LIMIT1) {
System.out.println();
System.out.println("iteration: " + iteration1);
// method #0
methodName = "null";
iteration2 = 0;
startNanos = System.nanoTime();
while (iteration2++ < ITERATION_LIMIT2) {
method0(s1, s2);
}
durationNanos = System.nanoTime() - startNanos;
System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));
// method #1
methodName = "s1.concat(s2)";
iteration2 = 0;
startNanos = System.nanoTime();
while (iteration2++ < ITERATION_LIMIT2) {
method1(s1, s2);
}
durationNanos = System.nanoTime() - startNanos;
System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));
// method #2
iteration2 = 0;
startNanos = System.nanoTime();
methodName = "s1 + s2";
while (iteration2++ < ITERATION_LIMIT2) {
method2(s1, s2);
}
durationNanos = System.nanoTime() - startNanos;
System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));
// method #3
iteration2 = 0;
startNanos = System.nanoTime();
methodName = "new StringBuilder(s1).append(s2).toString()";
while (iteration2++ < ITERATION_LIMIT2) {
method3(s1, s2);
}
durationNanos = System.nanoTime() - startNanos;
System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));
// method #4
iteration2 = 0;
startNanos = System.nanoTime();
methodName = "new StringBuffer(s1).append(s2).toString()";
while (iteration2++ < ITERATION_LIMIT2) {
method4(s1, s2);
}
durationNanos = System.nanoTime() - startNanos;
System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));
// method #5
iteration2 = 0;
startNanos = System.nanoTime();
methodName = "String.format(\"%s%s\", s1, s2)";
while (iteration2++ < ITERATION_LIMIT2) {
method5(s1, s2);
}
durationNanos = System.nanoTime() - startNanos;
System.out.println(String.format("%50s: %6.1f nanos", methodName, ((double) durationNanos) / ITERATION_LIMIT2));
}
System.out.println();
System.out.println("Tests complete");
}
public static String method0(String s1, String s2) {
return "";
}
public static String method1(String s1, String s2) {
return s1.concat(s2);
}
public static String method2(String s1, String s2) {
return s1 + s2;
}
public static String method3(String s1, String s2) {
return new StringBuilder(s1).append(s2).toString();
}
public static String method4(String s1, String s2) {
return new StringBuffer(s1).append(s2).toString();
}
public static String method5(String s1, String s2) {
return String.format("%s%s", s1, s2);
}
}
Run Code Online (Sandbox Code Playgroud)
您应该使用在运行时生成的String(如UUID.randomUUID().toString())进行测试,而不是在编译时(如"my string").我的结果是
plus: 118 ns
concat: 52 ns
builder1: 102 ns
builder2: 66 ns
buffer1: 119 ns
buffer2: 87 ns
Run Code Online (Sandbox Code Playgroud)
有了这个实现:
private static long COUNT = 10000000;
public static void main(String[] args) throws Exception {
String s1 = UUID.randomUUID().toString();
String s2 = UUID.randomUUID().toString();
for(String methodName : new String[] {
"none", "plus", "concat", "builder1", "builder2", "buffer1", "buffer2"
}) {
Method method = ConcatPerformanceTest.class.getMethod(methodName, String.class, String.class);
long time = System.nanoTime();
for(int i = 0; i < COUNT; i++) {
method.invoke((Object) null, s1, s2);
}
System.out.println(methodName + ": " + (System.nanoTime() - time)/COUNT + " ns");
}
}
public static String none(String s1, String s2) {
return null;
}
public static String plus(String s1, String s2) {
return s1 + s2;
}
public static String concat(String s1, String s2) {
return s1.concat(s2);
}
public static String builder1(String s1, String s2) {
return new StringBuilder(s1).append(s2).toString();
}
public static String builder2(String s1, String s2) {
return new StringBuilder(s1.length() + s2.length()).append(s1).append(s2).toString();
}
public static String buffer1(String s1, String s2) {
return new StringBuffer(s1).append(s2).toString();
}
public static String buffer2(String s1, String s2) {
return new StringBuffer(s1.length() + s2.length()).append(s1).append(s2).toString();
}
Run Code Online (Sandbox Code Playgroud)
对于标题中的问题:String.concat通常是连接两个Strings 的最快方式(但请注意null).不涉及[超大]中间缓冲区或其他对象.奇怪的+是编译成相对低效的代码涉及StringBuilder.
但是,你的身体问题指向其他问题.用于为地图生成键的字符串连接是常见的"反成语".这是一个黑客,容易出错.您确定生成的密钥是唯一的吗?在为某些尚未知的要求维护代码后,它是否仍然是唯一的?最好的方法是为密钥创建一个不可变的值类.使用List和通用元组类是一个草率的黑客.
| 归档时间: |
|
| 查看次数: |
44685 次 |
| 最近记录: |