Videos
parseInt is the way to go. The Integer documentation says
Use parseInt(String) to convert a string to a int primitive, or use valueOf(String) to convert a string to an Integer object.
parseInt is likely to cover a lot of edge cases that you haven't considered with your own code. It has been well tested in production by a lot of users.
I invite you to look at the source code of the parseInt function. Your naïve function is faster, but it also does way less. Edge cases, such as the number being to large to fit into an int or not even being a number at all, will produce undetectable bogus results with your simple function.
It is better to just trust that the language designers have done their job and have produced a reasonably fast implementation of parsing integers. Real optimization is probably elsewhere.
Usually this is done like this:
- init result with 0
- for each character in string do this
- result = result * 10
- get the digit from the character ('0' is 48 ASCII (or 0x30), so just subtract that from the character ASCII code to get the digit)
- add the digit to the result
- return result
Edit: This works for any base if you replace 10 with the correct base and adjust the obtaining of the digit from the corresponding character (should work as is for bases lower than 10, but would need a little adjusting for higher bases - like hexadecimal - since letters are separated from numbers by 7 characters).
Edit 2: Char to digit value conversion: characters '0' to '9' have ASCII values 48 to 57 (0x30 to 0x39 in hexa), so in order to convert a character to its digit value a simple subtraction is needed. Usually it's done like this (where ord is the function that gives the ASCII code of the character):
Copydigit = ord(char) - ord('0')
For higher number bases the letters are used as 'digits' (A-F in hexa), but letters start from 65 (0x41 hexa) which means there's a gap that we have to account for:
Copydigit = ord(char) - ord('0')
if digit > 9 then digit -= 7
Example: 'B' is 66, so ord('B') - ord('0') = 18. Since 18 is larger than 9 we subtract 7 and the end result will be 11 - the value of the 'digit' B.
One more thing to note here - this works only for uppercase letters, so the number must be first converted to uppercase.
The source code of the Java API is freely available. Here's the parseInt() method. It's rather long because it has to handle a lot of exceptional and corner cases.
Copypublic static int parseInt(String s, int radix) throws NumberFormatException {
if (s == null) {
throw new NumberFormatException("null");
}
if (radix < Character.MIN_RADIX) {
throw new NumberFormatException("radix " + radix +
" less than Character.MIN_RADIX");
}
if (radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" greater than Character.MAX_RADIX");
}
int result = 0;
boolean negative = false;
int i = 0, max = s.length();
int limit;
int multmin;
int digit;
if (max > 0) {
if (s.charAt(0) == '-') {
negative = true;
limit = Integer.MIN_VALUE;
i++;
} else {
limit = -Integer.MAX_VALUE;
}
multmin = limit / radix;
if (i < max) {
digit = Character.digit(s.charAt(i++), radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
} else {
result = -digit;
}
}
while (i < max) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++), radix);
if (digit < 0) {
throw NumberFormatException.forInputString(s);
}
if (result < multmin) {
throw NumberFormatException.forInputString(s);
}
result *= radix;
if (result < limit + digit) {
throw NumberFormatException.forInputString(s);
}
result -= digit;
}
} else {
throw NumberFormatException.forInputString(s);
}
if (negative) {
if (i > 1) {
return result;
} else { /* Only got "-" */
throw NumberFormatException.forInputString(s);
}
} else {
return -result;
}
}
You could return an Integer instead of an int, returning null on parse failure.
It's a shame Java doesn't provide a way of doing this without there being an exception thrown internally though - you can hide the exception (by catching it and returning null), but it could still be a performance issue if you're parsing hundreds of thousands of bits of user-provided data.
EDIT: Code for such a method:
public static Integer tryParse(String text) {
try {
return Integer.parseInt(text);
} catch (NumberFormatException e) {
return null;
}
}
Note that I'm not sure off the top of my head what this will do if text is null. You should consider that - if it represents a bug (i.e. your code may well pass an invalid value, but should never pass null) then throwing an exception is appropriate; if it doesn't represent a bug then you should probably just return null as you would for any other invalid value.
Originally this answer used the new Integer(String) constructor; it now uses Integer.parseInt and a boxing operation; in this way small values will end up being boxed to cached Integer objects, making it more efficient in those situations.
What behaviour do you expect when it's not a number?
If, for example, you often have a default value to use when the input is not a number, then a method such as this could be useful:
public static int parseWithDefault(String number, int defaultVal) {
try {
return Integer.parseInt(number);
} catch (NumberFormatException e) {
return defaultVal;
}
}
Similar methods can be written for different default behaviour when the input can't be parsed.
String myString = "1234";
int foo = Integer.parseInt(myString);
If you look at the Java documentation you'll notice the "catch" is that this function can throw a NumberFormatException, which you can handle:
int foo;
try {
foo = Integer.parseInt(myString);
}
catch (NumberFormatException e) {
foo = 0;
}
(This treatment defaults a malformed number to 0, but you can do something else if you like.)
Alternatively, you can use an Ints method from the Guava library, which in combination with Java 8's Optional, makes for a powerful and concise way to convert a string into an int:
import com.google.common.primitives.Ints;
int foo = Optional.ofNullable(myString)
.map(Ints::tryParse)
.orElse(0)
For example, here are two ways:
Integer x = Integer.valueOf(str);
// or
int y = Integer.parseInt(str);
There is a slight difference between these methods:
valueOfreturns a new or cached instance ofjava.lang.IntegerparseIntreturns primitiveint.
The same is for all cases: Short.valueOf/parseShort, Long.valueOf/parseLong, etc.
int x = Integer.parseInt("x");
Based on above code, A string is internally a character and each character in Java has a corresponding Unicode value I believe. Then why is not the Java compiler smart enough to convert the "x" into its corresponding unicode value?