Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Way to parseInt without try-catch in Java 8?

Tags:

java

java-8

Is there a better way to try to convert to int a string that can be or not an integer? Integer.parseInt(String value) will work well with "25" or "019" but not with "hello" or "8A". In Java 8, we have optional values, for example:

public static void main(String[] args) {
    Optional<Integer> optionalResult = functionThatReturnsOptionalInteger();
    Integer finalValue = optionalResult.orElse(0);
    System.out.println(finalValue);
}

public static Optional<Integer> functionThatReturnsOptionalInteger() {
    Integer[] ints = new Integer[0];
    return Stream.of(ints).findAny();
}

You do not need to check nulls, because the Optional wrapper expose useful methods to deal with this kind of situations.

But if you want to parseInt a string, that can be null, or does not contains a valid integer, the solution is the same as always:

public static Integer parseIntOrDefault(String toParse, int defaultValue) {
    try {
        return Integer.parseInt(toParse);
    } catch (NumberFormatException e) {
        return defaultValue;
    }
}

How can improve this with Java 8 features, why Integer.parseInt() has not been overloaded to return an Optional in case of bad argument? (Or just add a new method Integer.parseIntOptional() to Integer wrapper)

like image 636
C.P.O Avatar asked Sep 15 '17 13:09

C.P.O


People also ask

What can I use instead of parseInt?

parseFloat( ) parseFloat() is quite similar to parseInt() , with two main differences. First, unlike parseInt() , parseFloat() does not take a radix as an argument. This means that string must represent a floating-point number in decimal form (radix 10), not octal (radix 8) or hexadecimal (radix 6).

When parseInt () method can be used in Java?

The method generally used to convert String to Integer in Java is parseInt(). This method belongs to Integer class in java. lang package. It takes a valid string as a parameter and parses it into primitive data type int.

Can parseInt return null?

If parseInt() is given an empty string or a null value it will also return NaN, rather than converting them to 0.

Does parseInt throw error?

parseInt method as a parameter. The method throws an error if the string cannot be parsed into an integer. Note, that the code within the catch block is executed only if an exception is thrown.


3 Answers

There doesn't exist anything like this in the standard library afaik, but you can write a method that parses a String into an Optional<Integer> like this:

public static Optional<Integer> parseInt(String toParse) {
    try {
        return Optional.of(Integer.parseInt(toParse));
    } catch (NumberFormatException e) {
        return Optional.empty();
    }
}
like image 96
Felk Avatar answered Sep 18 '22 12:09

Felk


Unlike other answers that are now deleted, I don't think this really has to do with Java being backwards-compatible.

Because an empty Optional represents a value that is absent, it would mean that the method actually worked but no results are returned.

However, parsing hello as an integer will not work and has to throw an exception, because it is an error rather than an empty result. Keep in mind that NumberFormatException extends IllegalArgumentException.

More generally speaking, Optional was made for dealing with possibly absent values (instead of using null for that), and not for error handling. Also, Optional doesn't provide any way to know what is the error and why there is one.

like image 25
Jonathan Avatar answered Sep 20 '22 12:09

Jonathan


I don’t want to speculate why such method does not exist, but if you like neither, perform a pre-test nor catch an exception, you need a re-implementation, e.g.

public static OptionalInt parseInt(String s) {
    if(s.isEmpty()) return OptionalInt.empty();
    final int len = s.length(), limit;
    final boolean negative;
    int i = 0;
    switch(s.charAt(0)) {
        case '-':
            i=1;
            if(len==1) return OptionalInt.empty();
            negative = true;
            limit = Integer.MIN_VALUE;
            break;
        case '+':
            i=1;
            if(len==1) return OptionalInt.empty();
            // fall-through
        default:
            negative = false;
            limit = -Integer.MAX_VALUE;
    }
    final int limitBeforeMul = limit / 10;
    int result = 0;
    for(; i < len; i++) {
        int digit = Character.digit(s.charAt(i), 10);
        if(digit < 0 || result < limitBeforeMul || (result *= 10) < limit + digit)
            return OptionalInt.empty();
        result -= digit;
    }
    return OptionalInt.of(negative? result: -result);
}

This basically does the same as Integer.parseInt, but returns an empty OptionalInt for invalid strings instead of throwing an exception…

As you might notice, the hardest part is to handle numbers close to Integer.MIN_VALUE resp. Integer.MAX_VALUE correctly.

like image 24
Holger Avatar answered Sep 19 '22 12:09

Holger