To convert an int (primitive integer) value into a String, we can use either String.valueOf() or Integer.toString() method. Internally, the former calls the latter, so Integer.toString() should be preferred.
This Java tutorial discusses the following techniques for converting an int
to a String
, and we’ll conduct a performance comparison to understand the efficiency of each method.
int num = 100;
String value1 = Integer.toString( num ); // Works for Integer too
String value2 = String.valueOf( num ); // Works for Integer too
1. Using Integer.toString()
The Integer.toString(int) returns a string representing the specified int passed as a method argument. By default, the argument is converted to signed decimal (radix 10) in string format.
String toString(int i);
For example, we can pass any positive or negative value and get its value in a string.
Assertions.assertEquals("0", Integer.toString(0));
Assertions.assertEquals("40", Integer.toString(40));
Assertions.assertEquals("-40", Integer.toString(-40));
1.1. No Exception Thrown
Be careful to not exceed the maximum or minimum value of the int type which is 2147483647 and -2147483648. We will get unexpected results in case we cross the upper or lower bounds.
Assertions.assertEquals("2147483647", Integer.toString(Integer.MAX_VALUE));
Assertions.assertEquals("-2147483648", Integer.toString(Integer.MAX_VALUE + 1));
Assertions.assertEquals("-2147483648", Integer.toString(Integer.MIN_VALUE));
Assertions.assertEquals("2147483647", Integer.toString(Integer.MIN_VALUE - 1));
1.2. Binary, Octal and Hex Strings
Note that we can use several other inbuilt methods if we want to get the String value in other base values. The default base is 10.
Assertions.assertEquals("101000", Integer.toBinaryString(40));
Assertions.assertEquals("50", Integer.toOctalString(40));
Assertions.assertEquals("28", Integer.toHexString(40));
2. Using String.valueOf()
The String.valueOf(int i) returns the string representation of the int argument. It internally invokes the Integer.toString() so the the representations are always the same.
String valueOf(int i);
Let us test out the int values again as in the previous section.
Assertions.assertEquals("0", String.valueOf(0));
Assertions.assertEquals("40", String.valueOf(40));
Assertions.assertEquals("-40", String.valueOf(-40));
Assertions.assertEquals("2147483647", String.valueOf(Integer.MAX_VALUE));
Assertions.assertEquals("-2147483648", String.valueOf(Integer.MAX_VALUE + 1));
Assertions.assertEquals("-2147483648", String.valueOf(Integer.MIN_VALUE));
Assertions.assertEquals("2147483647", String.valueOf(Integer.MIN_VALUE - 1));
3. Performance Comparison
In this section, we will use JMH to test the performance of both discussed methods as well as a few other unconventional approaches as listed below:
These methods also work for a boxed Integer object. Since boxing/unboxing are costly operations, we strive to avoid them unless they are really necessary. But, you never know when an un-boxing operation may sneak “behind the scene” and impact the performance of the application.
We have written the JMH class to benchmark all these methods (in Java 21) as follows:
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
@State(Scope.Thread)
public class IntToStringBenchmark {
private ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void methodIntegerToString(Blackhole blackhole) {
int i = threadLocalRandom.nextInt(1_00_000, 9_99_999);
String s = Integer.toString(i);
blackhole.consume(s);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void methodStringValueOf(Blackhole blackhole) {
int i = threadLocalRandom.nextInt(1_00_000, 9_99_999);
String s = String.valueOf(i);
blackhole.consume(s);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void methodStringFormat(Blackhole blackhole) {
int i = threadLocalRandom.nextInt(1_00_000, 9_99_999);
String s = String.format("%d", i);
blackhole.consume(s);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public void methodStringTemplate(Blackhole blackhole) {
int i = threadLocalRandom.nextInt(1_00_000, 9_99_999);
String s = STR."\{i}";
blackhole.consume(s);
}
public static void main(String[] args) throws Exception {
Options opt = new OptionsBuilder()
.include(IntToStringBenchmark.class.getSimpleName())
.forks(1)
.build();
new Runner(opt).run();
}
}
The following is the result of the performance tests:
Benchmark Method Syntax Used Performance (Avg Time per Operation) methodIntegerToString Integer.toString(int) 0.012 methodStringValueOf String.valueOf(int) 0.016 methodStringTemplate STR.”\{i}” 0.019 methodStringFormat String.format(“%d”, int) 0.0143I also tried to peek into the bytecode generated for these statements to understand why they perform they are:
//******** methodIntegerToString **********/
13: invokestatic #25 // Method java/lang/Integer.toString:(I)Ljava/lang/String;
//******** methodStringValueOf **********/
13: invokestatic #45 // Method java/lang/String.valueOf:(I)Ljava/lang/String;
//******** methodStringFormat **********/
12: ldc #49 // String %d
14: iconst_1
15: anewarray #2 // class java/lang/Object
18: dup
19: iconst_0
20: iload_2
21: invokestatic #37 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
24: aastore
25: invokestatic #51 // Method java/lang/String.format:(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
//******** methodStringTemplate **********/
13: invokedynamic #55, 0 // InvokeDynamic #0:makeConcatWithConstants:(I)Ljava/lang/String;
There are two clear conclusions that we can extract from the results:
The results of these benchmarks were obtained on an 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz machine with Windows 11 (16GB RAM). Please feel free to test it on different configurations since the JMH results are dependent on the machines too.
4. ConclusionIn Java, converting an int value to a String is not a difficult task but knowing which method may save us a few CPU cycles is worth knowing. In this case, we should always prefer the Integer.toString() to int to String conversions.
Happy Learning !!
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4