1

So I have seen this question, which gives several ways to convert integers to Strings, but I am wondering if there is any difference between them.

If I want to just convert an integer i to a string, then is there a difference between these three ways (and are some faster than others)?

i+""
Integer.toString(i)
String.valueOf(i)

I would be inclined to use the second or third since the first one just seems weird to me. On the other hand, if I wanted to convert an integer i to a string and then concatenate it to another string, s, I could do:

i+s
Integer.toString(i)+s
String.valueOf(i)+s

Here I would be inclined to use the first one since I am concatenating anyway. But my question is: are there any standard practices that should be used here, and what exactly are the differences (if any) among these three methods?

Community
  • 1
  • 1
Carmeister
  • 208
  • 2
  • 8

7 Answers7

8

The option 1 ""+i is actually interpreted by the compiler as option 1b new StringBuilder("").append(i).toString().

The second option String.valueOf(i) internally calls Integer.toString(i) and therefore has an overhead of one method call.

The third option Integer.toString(i) seems to be fastest in my benchmark bellow.

In my tests (aprx. average over multiple runs):

  • Option 1: ~64000 ms
  • Option 1b: ~64000 ms (same as option 1, due to equivalent compilation)
  • Option 2: ~86000 ms (due to additional method call)
  • Option 3: ~40000 ms

The simplistic benchmark code I used:

public static void main(String[] args) {

    int i = 0;
    String result;
    long time;

    time = System.currentTimeMillis();
    while (i < Integer.MAX_VALUE) {
        result = ""+i;
        i++;
    }
    System.out.println("Option 1: " + (System.currentTimeMillis() - time));

    i = 0;
    time = System.currentTimeMillis();
    while (i < Integer.MAX_VALUE) {
        result = new StringBuilder("").append(i).toString();
        i++;
    }
    System.out.println("Option 1b: " + (System.currentTimeMillis() - time));

    i = 0;
    time = System.currentTimeMillis();
    while (i < Integer.MAX_VALUE) {
        result = String.valueOf(i);
        i++;
    }
    System.out.println("Option 2: " + (System.currentTimeMillis() - time));

    i = 0;
    time = System.currentTimeMillis();
    while (i < Integer.MAX_VALUE) {
        result = Integer.toString(1);
        i++;
    }
    System.out.println("Option 3: " + (System.currentTimeMillis() - time));

}

As a conclusion, at least on my JVM (JDK 1.7.0_60 64bit) the option 3: Integer.toString(i) is the fastest and I'd recommend to use it.

The conclusion that ""+i is the fastest in one of the other posts is likely due to a flawed benchmark which enabled compilation into a constant.

Vladimír Schäfer
  • 15,375
  • 2
  • 51
  • 71
  • +1 for methodology. But I still believe: *There is no significant performance difference between these.* – Mansueli Jul 24 '14 at 18:43
  • I agree, the difference in most real world applications is negligible. – Vladimír Schäfer Jul 24 '14 at 18:44
  • You are not allowing for warm up. It takes time for the JVM to kick in. Either put some statements before the first while or run different tests where the ""+i happens not in the first run. You are also no allowing for cool down time between runs. Add a sleep between calls. – Cindy Langdon Jul 24 '14 at 18:47
2

A simple test revealed HUGE differences between them.

Allowing for start up and cool down between runs, then for every test, running to Integer.MAX_VALUE for every option, I got these results:

""+1 took 675 millis
String.valueOf(1) took 52244 millis
Integer.toString(1) took 53205 millis

Result: Whenever possible, use i+"" or ""+1.

Sense of social duty kicking in here: My tests were (as I indicated) ""+1, String.valueOf(1), and Integer.toString(1). When I re-run my tests I find the same results. HOWEVER, when I use variables, as indicated by ASantos and VSchäfer I get times similar between the solutions.

Whew. I feel better now.

Cindy Langdon
  • 611
  • 6
  • 12
  • 4
    I'm very hesitant to accept this benchmark without further details on your methodology. I suspect that what actually happened was that the compiler saw two constants and inlined it, instead of performing any computation at runtime. – MikeD Jul 24 '14 at 18:10
  • thats something to rely on – SparkOn Jul 24 '14 at 18:10
  • @CindyLangdon - Mike is right.. My system shows different result.. *84780 4908 94151* respectively. BTW I am using `NanoTime` – TheLostMind Jul 24 '14 at 18:16
  • @CindyLangdon - try using `""+i` where `int i=5;` and try the same test case and see the difference. The compiler is most probably inlining your constants (1 and ""). – TheLostMind Jul 24 '14 at 18:17
  • 1
    `""+i` allocates a `StringBuilder`, calls `append` with the empty string, calls `append` with the `int`, which calls `Integer.stringSize` to determine how much space is required, resizes the `StringBuilder` if necessary, and then calls `Integer.getChars`, the same method that `Integer.toString` relies on. "Use the source, Luke." – David Conrad Jul 24 '14 at 18:41
2

Good answers. I've tried it (just for fun) and got similar times.

""+i is interpreted as StringBuilder("").append(i).toString() where as ""+1 is inlined.

I suspect some of the benchmarks presented here were inlined.

Based on my tests I found these times:

Option 1 (K) ""+8  :            655 milliseconds
Option 1 (var) ""+i:          83462 milliseconds
Option 2 String.valueOf(i):   90685 milliseconds
Option 3 Integer.toString(i): 88764 milliseconds

Option 1 (K) is what I suspect some tests here were using. Option 2 is slightly better than option 4. Maybe due to some optimization in the JVM?

I am using a MacBook Pro, the JVM is 1.7.0_21

This is the source code I used:

public class Main{
    public static void main(String[] args) throws InterruptedException
    {
        // warm up the JVM
        for (int i = 0; i < 1000; i++)
        {
            String aString = ""+i;
        }

        long now = System.currentTimeMillis();
        for (int i = 0; i < Integer.MAX_VALUE; i++)
        {
            String aString = ""+8;
        }
        System.out.println("Option 1 (K) \"\"+8 "+(System.currentTimeMillis()-now));

        now = System.currentTimeMillis();
        for (int i = 0; i < Integer.MAX_VALUE; i++)
        {
            String aString = ""+i;
        }
        System.out.println("Option 1 (var) \"\"+i "+(System.currentTimeMillis()-now));

        Thread.sleep(1000); 
        now = System.currentTimeMillis();
        for (int i = 0; i < Integer.MAX_VALUE; i++)
        {
            String aString = String.valueOf(i);
        }
        System.out.println("Option 2 String.valueOf(i) "+(System.currentTimeMillis()-now));

        Thread.sleep(1000); 
        now = System.currentTimeMillis();
        for (int i = 0; i < Integer.MAX_VALUE; i++)
        {
            String aString = Integer.toString(i);
        }
        System.out.println("Option 3 Integer.toString(i) "+(System.currentTimeMillis()-now));

    }
}
Alexandre Santos
  • 8,170
  • 10
  • 42
  • 64
1
String.valueOf(i); 

actually calls

Integer.toString(i);

One more thing if you invoke toString() in a null object you will get a NullPointerException

Moreover the static valueOf() of String class takes different primitive parameters and offers more flexibility

SparkOn
  • 8,806
  • 4
  • 29
  • 34
1

Differences:

String to int

//overhead as you are appending a empty string with an int
""+i
//More generic (can be the same for float, double, long & int)
String.valueOf(i)
//Type Safe you know for sure that what you are converting is an Integer.
Integer.toString(i)

No, there are no standard way it all depends on what you are trying to accomplish, if you want your code to be more robust you might try the valueOf(), if you want to be certain that it is in fact a Integer than the second (the first is not recommended).

There is no significant performance difference between these 3.

The other way is analog to the comments of the String to int.

Mansueli
  • 6,223
  • 8
  • 33
  • 57
1

i+""; Tends to be computationally faster than the other two but as far as industry standards go, it tends to be frowned upon. I personally would use String.valueOf(i) but I believe Integer.toString(i) is also acceptable. i + "S" in the case of concatenation is also fine.

Terrik
  • 17
  • 5
  • 2
    Faster? Mind explaining/proving how and why? – Mansueli Jul 24 '14 at 17:54
  • If anything, it would be slower since it involves creating a StringBuilder and calling `append` twice, once with the int, and once with the empty string. Ultimately it uses the same logic in `Integer` to get the string representation of the number. It might not actually be slower, depending on what the JIT can do with it, but there's no way it can be faster. – David Conrad Jul 24 '14 at 18:36
  • Integer.toString(i) uses the following set of code: `if(i == Integer.MIN_VALUE) return "-2147483648; int size = (i < 0) ? stringSize(-1) + 1 : stringSize(i); char[] buf = new char[size]; getChars(i, size, buf); return new String(buf, true);` I could be wrong in assuming string creation, object creation, array instantiation and all the rest is slower than 2 StringBuilder appends. I will confess to not knowing a lot of what happens at the base level, but my impression was that there was less overhead in StringBuilder then in other objects. – Terrik Jul 24 '14 at 19:56
1

The source code of String.valueOf(int) is:

public static String valueOf(int i) {
    return Integer.toString(i);
}

Since the String class is final, this call will probably be inlined by the JIT.

In the case of i + "" it will create a StringBuilder and call its append(int) method, which ultimately results in a call to Integer.getChars, the same method that Integer.toString uses to get the string representation of the integer. It also calls the append(String) method to append the empty string, and then toString to get the resulting String from the StringBuilder.

David Conrad
  • 15,432
  • 2
  • 42
  • 54