在Java 8中没有try-catch的parseInt的方法?

时间:2017-09-15 13:57:11

标签: java java-8

有没有更好的方法尝试将int转换为可以是或不是整数的字符串? Integer.parseInt(String value)适用于“25”或“019”但不适用于“hello”或“8A”。 在Java 8中,我们有可选值,例如:

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();
}

您不需要检查空值,因为Optional包装器会提供有用的方法来处理这种情况。

但是如果你想parseInt一个字符串,可以是null,或者不包含有效整数,那么解决方案就像以前一样:

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

如何使用Java 8功能改进这一点,为什么Integer.parseInt()没有重载返回一个可选的以防错误? (或者只是将一个新方法Integer.parseIntOptional()添加到Integer包装器中)

6 个答案:

答案 0 :(得分:9)

标准库afaik中不存在这样的内容,但您可以编写一个方法,将String解析为Optional<Integer>,如下所示:

public static Optional<Integer> parseInt(String toParse) {
    try {
        return Optional.of(Integer.parseInt(toParse));
    } catch (NumberFormatException e) {
        return Optional.empty();
    }
}

答案 1 :(得分:6)

与现在已删除的其他答案不同,我认为这与Java向后兼容无关。

因为空Optional表示值不存在,这意味着该方法实际工作但未返回任何结果。

但是,将hello解析为整数将不起作用并且必须抛出异常,因为它是错误而不是空结果。请注意NumberFormatException扩展IllegalArgumentException

更一般地说,Optional是针对处理可能缺席的值(而不是使用null),而不是用于错误处理。此外,Optional没有提供任何方法来了解错误是什么以及错误是什么。

答案 2 :(得分:3)

我不想推测为什么这种方法不存在,但如果您既不喜欢,也不执行预测试或捕获异常,则需要重新实现,例如。

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);
}

这基本上与Integer.parseInt相同,但是对于无效字符串返回空OptionalInt而不是抛出异常......

您可能会注意到,最难的部分是处理接近Integer.MIN_VALUE的数字。 Integer.MAX_VALUE正确。

答案 3 :(得分:1)

没有try-catch并仍然返回一个Optional - 你可以做

Integer.MIN_VALUE

编辑:更新了正则表达式以支持负数

警告:正如评论中所指出的,如果解析后的字符串超出Integer.MAX_VALUEvec <- c(1.5,1.3,5.7)

答案 4 :(得分:1)

Google的Guava库提供了一种帮助方法来执行此操作:Ints.tryParse(String)。当无法解析字符串时,它将运行null。您可以检出documentation

答案 5 :(得分:0)

使用 Mutiny 可以这样写。

如果你只是想对结果做一些事情,你可以用一个表达式来做

Uni.createFrom()
  .item(() -> Integer.parseInt(toParse))
  .onFailure().recoverWithItem(defaultValue)
  .subscribe().with(i -> System.out.println(i));

或者创建一个符合预期的方法

    public static Integer parseIntOrDefault(String toParse, int defaultValue) {
        Integer[] toReturn = new Integer[]{null};
        Uni.createFrom()
           .item(() -> Integer.parseInt(toParse))
           .onFailure().recoverWithItem(defaultValue)
           .subscribe().with(i -> toReturn[0] = i);
        return toReturn[0];
}

此解决方案添加了一个库,但该库并非专门用于处理此问题。它使用反应式编程、期货、回调和流畅的 API,并被证明足够灵活来解决这个问题。