LoginSignup
1
1

More than 5 years have passed since last update.

Integer#parseIntを利用せずに文字列がintに変換できるかどうかを検査する

Last updated at Posted at 2017-05-15

「入力された文字列がint型に変換されるかどうかをチェックしたい」という場合、次のように判定しているソースコードを見かけることがあります。

try {
    Integer.parseInt(str);
    return true;
} catch (NumberFormatException e) {
    return false;
}

まず変換してみてダメならfalseにする、そして例外を握りつぶすなど、この方法には個人的に違和感があり、なんとなく敬遠の対象でした。身もふたもない言い方をすれば、生理的嫌悪感があります。

そういうわけでInteger#parseIntを利用せずに、与えられた文字列がintに変換できるかどうかチェックするメソッドを作っておきました(´・ω・`)

final public class IntegerUtils {

    public static void main(String[] args) {
        System.out.println(IntegerUtils.isInteger("123")); //=> true
        System.out.println(IntegerUtils.isInteger("-23")); //=> true
        System.out.println(IntegerUtils.isInteger("12A")); //=> false
        System.out.println(IntegerUtils.isInteger("ABC")); //=> false

        // 境界値でも正確に判定できている。
        System.out.println(IntegerUtils.isInteger("2147483647")); //=> true
        System.out.println(IntegerUtils.isInteger("2147483648")); //=> false
        System.out.println(IntegerUtils.isInteger("-2147483648")); //=> true
        System.out.println(IntegerUtils.isInteger("-2147483649")); //=> false

        // ==== 2017-05-16 テストケースを追加した。 ===
        System.out.println(IntegerUtils.isInteger("0")); //=> true
        System.out.println(IntegerUtils.isInteger("473")); //=> true
        System.out.println(IntegerUtils.isInteger("+42")); //=> true
        System.out.println(IntegerUtils.isInteger("-0")); //=> true

        System.out.println(IntegerUtils.isInteger("-")); //=> false
        System.out.println(IntegerUtils.isInteger("+5")); //=> true
        System.out.println(IntegerUtils.isInteger("123")); //=> true
        System.out.println(IntegerUtils.isInteger("١٢٣")); //=> true        
    }


    /**
     * 文字列が10進数の整数であり、かつintの範疇に収まるかどうかを判定する。
     * @param str 判定対象の文字列。
     * @return 文字列が10進数の整数であり、かつintの範疇に収まる場合はTrue.
     */
    public static final boolean isInteger(String str) {
        if (str == null
                || str.isEmpty()
                || str.equals("+")
                || str.equals("-")) {
            return false;
        }

        char first = str.charAt(0);
        int i = (first == '+' || first == '-') ? 1 : 0;
        int sign = (first == '-') ? -1 : 1;
        int len = str.length();
        long integer = 0;

        while (i < len) {
            char ch = str.charAt(i++);
            int digit = Character.digit(ch, 10);
            if (digit == -1) {
                return false;
            }

            integer = integer * 10 + sign * digit;
            if (integer < Integer.MIN_VALUE || Integer.MAX_VALUE < integer) {
                return false;
            }
        }
        return true;
    }



//    ==== 2017-05-16 ロジックに誤りがあったため全面的に修正した。 ===
//    /**
//     * 文字列が10進数の整数であり、かつintの範疇に収まるかどうかを判定する。
//     * @param str 判定対象の文字列。
//     * @return 文字列が10進数の整数であり、かつintの範疇に収まる場合はTrue.
//     */
//    public static final boolean isInteger(String str) {        
//        if (str == null || str.isEmpty()) {
//            return false;
//        }
//        
//        boolean isNegative = str.charAt(0) == '-';
//        int i = isNegative ? 1 : 0;
//        int sign = isNegative ? -1: 1;
//        int len = str.length();
//        long integer = 0;
//        
//        while (i < len) {
//            int digit = str.charAt(i++) - '0';
//            if (digit < 0 || 9 < digit) {
//                return false;
//            }
//            
//            integer = integer * 10 + sign * digit;
//            if (integer < Integer.MIN_VALUE || Integer.MAX_VALUE < integer) {
//                return false;
//            }
//        }
//        return true;
//    }
}

アルゴリズムというか、やっていることはごく単純で、与えられた引数が整数に変換できるかどうかを1文字ずつ検査しているだけ。Integer#parseIntを利用する方法と違いがあるとすれば、例外を利用していないということぐらいですが、「例外ならfalse」というよりは洗練されていると個人的には感じています。自己満足(´・ω・`)

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1