假设我有:
int someValue = 42;
现在我想将那个 int 值转换为字符串。哪种方法更有效?
// One
String stringValue = Integer.toString(someValue);
// Two
String stringValue = String.valueOf(someValue);
// Three
String stringValue = someValue + "";
我只是好奇它们之间是否有任何真正的区别或者一个比另一个更好?
假设我有:
int someValue = 42;
现在我想将那个 int 值转换为字符串。哪种方法更有效?
// One
String stringValue = Integer.toString(someValue);
// Two
String stringValue = String.valueOf(someValue);
// Three
String stringValue = someValue + "";
我只是好奇它们之间是否有任何真正的区别或者一个比另一个更好?
我测试了数字10的10m次赋值操作
One:
real 0m5.610s
user 0m5.098s
sys 0m0.220s
Two:
real 0m6.216s
user 0m5.700s
sys 0m0.213s
Three:
real 0m12.986s
user 0m11.767s
sys 0m0.489s
看起来似乎胜出了。
编辑: 在 Mac OS X 10.5 下,JVM 的标准位置为 '/usr/bin/java'。
java version "1.5.0_16" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b06-284) Java HotSpot(TM) Client VM (build 1.5.0_16-133, mixed mode, sharing)
更多编辑:
按要求提供代码
public class One {
public static void main(String[] args) {
int someValue = 10;
for (int i = 0; i < 10000000; i++) {
String stringValue = Integer.toString(someValue);
}
}
}
类似于第2和第3个案例
使用以下方式运行
javac *.java; time java One; time java Two; time java Three
String.valueOf()
。我的理由是这个调用不明确包含参数的类型,因此,如果以后你决定将其从int更改为double,则无需修改此调用。与#2相比,#1的速度增益仅仅是微不足道的,并且我们都知道,“过早地优化是万恶之源”。第三种解决方案是不可行的,因为它隐式创建了一个StringBuilder
并将组件(在本例中是数字和空字符串)附加到其中,最后将其转换为字符串。""+i
很慢的说法不符。它似乎被优化为与其他替代方案一样快。 - tucuxi看一下JRE的源代码,你可能会看到差异。或者没有任何差异。 事实上,String.valueOf(int foo)的实现如下:
public static String valueOf(int i) {
return Integer.toString(i, 10);
}
还有 Integer.toString(int foo, int radix) 方法
public static String toString(int i, int radix) {
...
if (radix == 10) {
return toString(i);
}
...
}
这意味着如果您使用十进制,最好直接调用Integer.toString(int foo)。对于其他情况,请使用Integer.toString(int foo, int radix)。
连接字符串的解决方案首先将int值转换为String,然后与空字符串连接。这显然是最昂贵的情况。
前两个示例实际上是相同的,因为String.valueOf(int)使用了Integer.toString(int)方法。第三个示例很丑陋,而且可能不够高效,因为在Java中连接操作速度较慢。
(与David Hanak相反。)
尽管根据cobbal的测量结果,#1似乎是最快的,但我强烈建议使用Integer.toString()。我的理由是,这个调用明确地包含了参数的类型,因此如果以后你决定将它从int改为double,那么就清楚地知道这个调用已经改变了。如果是二进制格式,你也会这样做,对吧?与#2相比,#1的速度增益仅仅是微不足道的,并且众所周知,“过早的优化是万恶之源”。
"" + int
的速度比David Hanak所示要慢。
String.valueOf()
调用Integer.toString()
。因此,使用Integer.toString()
更好。
因此,Integer.toString()
是最快的。
我的JDK 11微基准测试结果与目前被接受的答案非常不同,显示出最小的运行时间差异,并且完全没有内存使用/分配差异:
t (ms) method
12,30 "" + j
12,57 Integer.toString(j)
12.58 String.valueOf(j)
我实际上编写了这个微基准测试来解决另一个问题; 一位评论者建议我也在这里发布。以下是用于复制的代码(也来自该帖子):
package org.example;
import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
import com.google.caliper.Param;
import com.google.caliper.runner.CaliperMain;
public class Main {
@Param({"10", "100", "1000"})
int size;
private String[] output;
@BeforeExperiment
void setUp() {
output = new String[size];
}
@Benchmark void quote(int reps) {
for (int i = 0; i < reps; i++) {
for (int j = 0; j < size; j++) {
output[j] = "" + j;
}
}
}
@Benchmark void toString(int reps) {
for (int i = 0; i < reps; i++) {
for (int j = 0; j < size; j++) {
output[j] = Integer.toString(j);
}
}
}
@Benchmark void valueOf(int reps) {
for (int i = 0; i < reps; i++) {
for (int j = 0; j < size; j++) {
output[j] = String.valueOf(j);
}
}
}
/*
must have com.google.caliper:caliper:1.0-beta-3 in pom.xml; run with:
mvn clean compile exec:java -Dexec.mainClass="com.google.caliper.runner.CaliperMain" -Dexec.args="org.example.Main"
*/
public static void main(String[] args) {
CaliperMain.main(Main.class, args);
}
}