29

There are many ways of converting a String to an Integer object. Which is the most efficient among the below:

Integer.valueOf()
Integer.parseInt()
org.apache.commons.beanutils.converters.IntegerConverter

My usecase needs to create wrapper Integer objects...meaning no primitive int...and the converted data is used for read-only.

Lance Roberts
  • 22,383
  • 32
  • 112
  • 130
Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
  • I did some small test and surprised to see that Integer.valueOf is taking lot of time...any thoughts... [code] for (int i = 1; i <= Integer.MAX_VALUE / 100; i++) conversion [code] valueOf=0:00:18.094 parseInt=0:00:17.656 IntegerConverter=0:00:13.594 NumberUtils.toInt=0:00:13.734 – Aravind Yarram Jun 23 '09 at 03:50
  • http://stackoverflow.com/q/508665/2296787 check this – MBH Jul 31 '15 at 08:57

11 Answers11

29

If efficiency is your concern, then creating an Integer object is much more expensive than parsing it. If you have to create an Integer object, I wouldn't worry too much about how it is parsed.

Note: Java 6u14 allows you to increase the size of your Integer pool with a command line option -Djava.lang.Integer.IntegerCache.high=1024 for example.

Note 2: If you are reading raw data e.g. bytes from a file or network, the conversion of these bytes to a String is relatively expensive as well. If you are going to write a custom parser I suggest bypassing the step of conversing to a string and parse the raw source data.

Note 3: If you are creating an Integer so you can put it in a collection, you can avoid this by using GNU Trove (trove4j) which allows you to store primitives in collections, allowing you to drop the Integer creation as well.

Ideally, for best performance you want to avoid creating any objects at all.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
23

Your best bet is to use Integer.parseInt. This will return an int, but this can be auto-boxed to an Integer. This is slightly faster than valueOf, as when your numbers are between -128 and 127 it will use the Integer cache and not create new objects. The slowest is the Apache method.

private String data = "99";

public void testParseInt() throws Exception {
    long start = System.currentTimeMillis();
    long count = 0;
    for (int i = 0; i < 100000000; i++) {
        Integer o = Integer.parseInt(data);
        count += o.hashCode();
    }
    long diff = System.currentTimeMillis() - start;
    System.out.println("parseInt completed in " + diff + "ms");
    assert 9900000000L == count;
}

public void testValueOf() throws Exception {
    long start = System.currentTimeMillis();
    long count = 0;
    for (int i = 0; i < 100000000; i++) {
        Integer o = Integer.valueOf(data);
        count += o.hashCode();
    }
    long diff = System.currentTimeMillis() - start;
    System.out.println("valueOf completed in " + diff + "ms");
    assert 9900000000L == count;
}


public void testIntegerConverter() throws Exception {
    long start = System.currentTimeMillis();
    IntegerConverter c = new IntegerConverter();
    long count = 0;
    for (int i = 0; i < 100000000; i++) {
        Integer o = (Integer) c.convert(Integer.class, data);
        count += o.hashCode();
    }
    long diff = System.currentTimeMillis() - start;
    System.out.println("IntegerConverter completed in " + diff + "ms");
    assert 9900000000L == count;
}

parseInt completed in 5906ms
valueOf completed in 7047ms
IntegerConverter completed in 7906ms
brianegge
  • 29,240
  • 13
  • 74
  • 99
  • 3
    +1 for actually testing it!! FWIW, I think you could get even faster results from Integer.parseInt() if you didn't box the result.... this is worth an extra 10% or so on my machine – mikera Feb 10 '11 at 18:28
  • Could you please provide benchmarks? Adding exactly what you tried to come to your conclusion is helpful, sure, but I think it would be more meaningful to see your actual results COMBINED with your actual code that you used to come to this conclusion. For example, something like this http://nadeausoftware.com/articles/2009/08/java_tip_how_parse_integers_quickly – searchengine27 Jul 23 '15 at 19:30
10

I know this isn't amongst your options above. IntegerConverter is ok, but you need to create an instance of it. Take a look at NumberUtils in Commons Lang:

Commons Lang NumberUtils

this provides the method toInt:

static int toInt(java.lang.String str, int defaultValue) 

which allows you to specify a default value in the case of a failure.

NumberUtils.toInt("1", 0)  = 1

That's the best solution I've found so far.

Ken Y-N
  • 14,644
  • 21
  • 71
  • 114
Jonathan Holloway
  • 62,090
  • 32
  • 125
  • 150
10

I'm always amazed how quickly many here dismiss some investigation into performance problems. Parsing a int for base 10 is a very common task in many programs. Making this faster could have a noticable positive effect in many environments.

As parsing and int is actually a rather trivial task, I tried to implement a more direct approach than the one used in the JDK implementation that has variable base. It turned out to be more than twice as fast and should otherwise behave exactly the same as Integer.parseInt().

public static int intValueOf( String str )
{
    int ival = 0, idx = 0, end;
    boolean sign = false;
    char ch;

    if( str == null || ( end = str.length() ) == 0 ||
       ( ( ch = str.charAt( 0 ) ) < '0' || ch > '9' )
          && ( !( sign = ch == '-' ) || ++idx == end || ( ( ch = str.charAt( idx ) ) < '0' || ch > '9' ) ) )
        throw new NumberFormatException( str );

    for(;; ival *= 10 )
    {
        ival += '0'- ch;
        if( ++idx == end )
            return sign ? ival : -ival;
        if( ( ch = str.charAt( idx ) ) < '0' || ch > '9' )
            throw new NumberFormatException( str );
    }
}

To get an Integer object of it, either use autoboxing or explicit

Interger.valueOf( intValueOf( str ) ).

x4u
  • 13,877
  • 6
  • 48
  • 58
  • 2
    The reason that people dismiss it is because gaining a 50% improvement in something that takes 1/1,000,000th of your execution time is a waste. And for any non-trivial program, particularly those that involve databases, string-integer conversion should be far less than a millionth of the execution time. – kdgregory Jan 20 '10 at 13:04
  • 7
    @kdgregory: With todays ubiquitous prevalence of text based formats like XML, JSON and HTTP parsing numbers from strings is actually a very common task in many non trivial programs. I'd rather say if your programs still spend only very little time in this kind of code they are probably very inefficient somewhere else. – x4u Jan 20 '10 at 15:44
  • I don't agree with your use of "inefficient": A simple web request will take 100 milliseconds or so to execute. Parsing the request may take 100 *microseconds*. The former far overshadows the latter, and there's no "efficient" or "inefficient" involved. Nor much that you can do about it. – kdgregory Jan 20 '10 at 16:29
  • 2
    If you're looking to improve the overall throughput of your program the rules haven't changed since I started working 25+ years ago: you create a realistic workload, profile your application with that workload, and optimize the pieces that actually consume significant amounts of time. Anything else is wasted effort. – kdgregory Jan 20 '10 at 16:31
  • 1
    I totally agree with you. Profiling is the only way to know what's worth to optimize. But if this shows that your request handling takes 1000 times more time than processing the request, you are either doing some serious work there or wasting time in this code. I.e. using uncached database access in request handlers is something I would consider unacceptable inefficent for high load servers in most scenarios. – x4u Jan 20 '10 at 16:52
  • I let it run through a benchmark-test with jdk-1.5/1.6 mode client/server, with 100 000 and 3 000 000 cases. Machine centrino single 1.6Ghz, Linux, sun-sdk/vm. Result: no significant difference for 100 000 cases, about 0.1s client mode, 0.3s server mode each. With 3M cases: cm: 1.4s x4u-code / 1.8s jvm-code, sm: 1s/1s, in prosa: No difference in server mode for high numbers, and no difference for low numbers. – user unknown Mar 20 '11 at 11:47
  • Although I just about always rail against optimization I just found the same thing to be true--50% gain for the basic parsing an int (in an app that did little else). – Bill K Oct 18 '11 at 00:47
  • I'm doing a complex argmax calculation for witch i use String because Long and Integer is to small. I'm doing string to int convertions most of the time (more than 20 min. a run). Every little improvements for this task helps a lot. Thank you @x4u for taking this serious. I'm just wondering if the implementation Jay Askren provided is faster or slower than yours? – Spenhouet Jan 24 '17 at 18:56
  • The behaviour slightly differ from Integer.parseInt as it accept leading plus character. Check condition should looks like if (value == null || (end = value.length()) == 0 || ((ch = value.charAt(0)) < '0' || ch > '9') && (!((sign = ch == '-') || ch=='+') || ++idx == end || ((ch = value.charAt(idx)) < '0' || ch > '9'))) throw new ... – Konstantin Alexandrov May 07 '18 at 14:58
6

Here's a good article comparing the performance of different methods of parsing integers

And here's the code used, with overflow/underflow checks.

public static int parseInt( final String s )
{
    if ( string == null )
        throw new NumberFormatException( "Null string" );

    // Check for a sign.
    int num  = 0;
    int sign = -1;
    final int len  = s.length( );
    final char ch  = s.charAt( 0 );
    if ( ch == '-' )
    {
        if ( len == 1 )
            throw new NumberFormatException( "Missing digits:  " + s );
        sign = 1;
    }
    else
    {
        final int d = ch - '0';
        if ( d < 0 || d > 9 )
            throw new NumberFormatException( "Malformed:  " + s );
        num = -d;
    }

    // Build the number.
    final int max = (sign == -1) ?
        -Integer.MAX_VALUE : Integer.MIN_VALUE;
    final int multmax = max / 10;
    int i = 1;
    while ( i < len )
    {
        int d = s.charAt(i++) - '0';
        if ( d < 0 || d > 9 )
            throw new NumberFormatException( "Malformed:  " + s );
        if ( num < multmax )
            throw new NumberFormatException( "Over/underflow:  " + s );
        num *= 10;
        if ( num < (max+d) )
            throw new NumberFormatException( "Over/underflow:  " + s );
        num -= d;
    }

    return sign * num;
}

And even faster implementation, without overflow/underflow checks.

public static int parseInt( final String s )
{
    // Check for a sign.
    int num  = 0;
    int sign = -1;
    final int len  = s.length( );
    final char ch  = s.charAt( 0 );
    if ( ch == '-' )
        sign = 1;
    else
        num = '0' - ch;

    // Build the number.
    int i = 1;
    while ( i < len )
        num = num*10 + '0' - s.charAt( i++ );

    return sign * num;
} 
Jay Askren
  • 10,282
  • 14
  • 53
  • 75
  • 1
    I had to convert an arbitrary length array of `String` numbers into `int`s, so efficiency *is* important. I used your faster version, but removed sign checking to get rid of the extra `if`, because I don't have negative numbers. – lenooh Jul 30 '18 at 20:58
5

Don't even waste time thinking about it. Just pick one that seems to fit with the rest of the code (do other conversions use the .parse__() or .valueOf() method? use that to be consistent).

Trying to decide which is "best" detracts your focus from solving the business problem or implementing the feature.

Don't bog yourself down with trivial details. :-)

On a side note, if your "use case" is specifying java object data types for your code - your BA needs to step back out of your domain. BA's need to define "the business problem", and how the user would like to interact with the application when addressing the problem. Developers determine how best to build that feature into the application with code - including the proper data types / objects to handle the data.

Ron Savage
  • 10,923
  • 4
  • 26
  • 35
  • we have been using IntegerConverter consistently (across 70-80) classes. But IntegrConverter seems to use reflection creating Intger objects...convert(Integer.class,-1). So consistency is not the issue but efficiency! tx anyway – Aravind Yarram Jun 23 '09 at 03:46
  • 1
    That's too bad, as I like that method the least because there are "built in" simpler ways to do it. :-) I can't however imagine it causing any kind of performance problem - so I would stick to the "if it ain't broke, don't fix it" rule. – Ron Savage Jun 23 '09 at 03:53
  • 19
    totally agree with the BA point, but -1 overall for not answering the actual question and making the assumption that performance doesn't matter when the question is explicitly about efficiency. – mikera Feb 10 '11 at 18:39
  • 3
    @mikera I agree. This should not be the accepted answer, or upvoted at all. The 'answer' is entirely subjective and opinion based, and does not even make any attempt to answer the question that was asked. – searchengine27 Jul 23 '15 at 19:27
  • 1
    Sometimes the business problem is that the system is not fast enough, because developers thought the details did not matter. I have had systems where our bottleneck was parsing integers, and speeding that up made a system much more responsive and usable. On a side note, I'm not sure how the BA is relevant to this question. The OP does not mention the BA was trying to design there system. – Jay Askren Feb 04 '16 at 19:13
  • 4
    This question is the top Google result for people with billions of numbers to parse as quickly as possible, and the accepted answer is not useful in any way. – Thom Mar 25 '17 at 18:10
  • Parsing string representation of coordinates in hundred thousands is a business problem and performance could not be neglected. Real case. – Stan Sokolov Oct 08 '19 at 17:25
  • It matters what your data source is. If you have a data source with a lot of non-integer values in it (i.e., dirty data), the Java implementation of this will throw a NumberFormatException for every bad number. Put that in the middle of a couple of loops and you have a major hotspot, which is exactly what I have observed in YourKit. – Jonathan Locke Oct 20 '20 at 19:05
5

If efficiency is your concern, use int: it is much faster than Integer.

Otherwise, class Integer offers you at least a couple clear, clean ways:

Integer myInteger = new Integer(someString);
Integer anotherInteger = Integer.valueOf(someOtherString);
Jim Ferrans
  • 30,582
  • 12
  • 56
  • 83
  • I agree. Using the Integer class seems counter to the efficiency concern. Unless of course the efficiency is with regards to just string conversion, rather than integer storage or manipulation. – aberrant80 Jun 23 '09 at 06:15
  • Use the Integer.valueOf(someOtherString), it's smarter and can possibly use cached Integer instances. – deterb Jul 17 '09 at 03:06
5

I tried a comparison of valueOf, parseInt, Ints.tryParse, NumberUtils.createInteger and NumberUtils.toInt with the program below. I was on jdk 1.8.0

As expected, the methods that did not need to create an Integer object were the fastest. My results were:

valueOf took: 77
parseInt took: 61
Ints.tryParse took: 117
numberUtils.createInteger took: 169
numberUtils.toInt took: 63 

So the summary is:

If you can get by using an int, use Integer.parseInt.

If you absolutely need an Integer, use Integer.valueOf

If you need the convenience of not handling exceptions when you parse, or if you are unsure of the format of the input (i.e its a string that need not be a number) use Ints.tryParse

The code I used was:

public class HelloWorld {

public static int limit = 1000000;
public static String sint = "9999";

public static void main(String[] args) {

    long start = System.currentTimeMillis();
    for (int i = 0; i < limit; i++) {
       Integer integer = Integer.valueOf(sint);
    }
    long end = System.currentTimeMillis();

    System.out.println("valueOf took: " + (end - start));


    start = System.currentTimeMillis();
    for (int i = 0; i < limit; i++) {
        int integer = Integer.parseInt(sint);
    }
    end = System.currentTimeMillis();

    System.out.println("parseInt took: " + (end - start));


    start = System.currentTimeMillis();
    for (int i = 0; i < limit; i++) {
        int integer = Ints.tryParse(sint);
    }
    end = System.currentTimeMillis();

    System.out.println("Ints.tryParse took: " + (end - start));


    start = System.currentTimeMillis();
    for (int i = 0; i < limit; i++) {
        Integer integer = NumberUtils.createInteger(sint);
    }
    end = System.currentTimeMillis();

    System.out.println("numberUtils.createInteger took: " + (end - start));

    start = System.currentTimeMillis();
    for (int i = 0; i < limit; i++) {
        int integer = NumberUtils.toInt(sint);
    }
    end = System.currentTimeMillis();

    System.out.println("numberUtils.toInt took: " + (end - start));

}
}
Somaiah Kumbera
  • 7,063
  • 4
  • 43
  • 44
0

ParseInt returns an int, not a java.lang.Integer, so if you use tat method you would have to do

new Integer (Integer.parseInt(number));

I´ve heard many times that calling Integer.valueOf() instead of new Integer() is better for memory reasons (this coming for pmd)

In JDK 1.5, calling new Integer() causes memory allocation. Integer.valueOf() is more memory friendly.

http://pmd.sourceforge.net/rules/migrating.html

In addition to that, Integer.valueOf allows caching, since values -127 to 128 are guaranteed to have cached instances. (since java 1.5)

Tom
  • 43,810
  • 29
  • 138
  • 169
  • 2
    Java now supports auto-boxing, the automatic conversion between boxed and primitive types. So "Integer i = new Integer (Integer.parseInt(number));" is better written "Integer i = Integer.parseInt(number);" – Jim Ferrans Jun 23 '09 at 05:57
0

Herro - kinda new to Java so forgive my ignorance.

I was searching for a a way to parse a mixed string (letters & numbers) into an INT (kinda like javascript does). Couldn't find anything in the JAVADOC files so after much searching i just wrote a function that does it:

// This function takes a string mixed with numbers and letters and returns an INT with
// the first occurrence of a number (INT) in said string, ignoring the rest;
// -- Basically, loop checks if char is a digit, if yes, puts digit back into new array, if no, puts a whitespace in its place
// this creates an array with only digits; By converting it to a string and then trimming whitespaces, it gets parsed into an INT


public static int mixedStringToInt (String str) {

    boolean flag = true;
    boolean isNumber = false;
    final String refNumbers = "0123456789";

    int strlen = str.length();
    char[] numberArray = new char[strlen];
    char[] stringArray = str.toCharArray();

    for (int i = 0; i < strlen;i++){
        if(refNumbers.indexOf(stringArray[i]) > 0 && flag){
            // if current char is a digit
            isNumber = true;
            while (flag){
                numberArray[i] = stringArray[i];
                if(i+1 >= strlen || refNumbers.indexOf(stringArray[i+1]) < 0) flag = false;
                i++;
            }
        } else {
            // if current char is not a digit
            numberArray[i] = ' ';
        }
    }
    if (isNumber){
        return Integer.valueOf(new String(numberArray).trim());
    } else return 0;
}





Is this useful for anyone besides me? Did i waste my time writing this as there is already a method that does what i wanted to do?

Matt
  • 278
  • 3
  • 12
0

Another way is this method:

public class stringtoInteger {

    private static int stringtoInteger(String x) {
        String value = "";
        for (int i = 0; i < x.length(); i++) {
            char character = x.charAt(i);
            if (Character.isDigit(character)) {
                value = value + character;
            }
        }
        return Integer.parseInt(value);
    }
}  

Hope it helps!

Jack
  • 131,802
  • 30
  • 241
  • 343