Javaで文字列が数値かどうかを調べる

Javaで文字列が数値かどうかを確認する

1. 前書き

多くの場合、Strings, を操作しているときに、String が有効な数値であるかどうかを判断する必要があります。

In this tutorial, we’ll explore multiple ways to detect if the given String is numeric、最初にプレーンJavaを使用し、次に正規表現を使用し、最後に外部ライブラリを使用します。

さまざまな実装について話し合ったら、ベンチマークを使用して、どの方法が最適かを判断します。

メインコンテンツに進む前に、いくつかの前提条件から始めましょう。

2. 前提条件

この記事の後半では、ApacheCommons外部ライブラリを使用します。 この依存関係を含めるには、pom.xmlに次の行を追加します。


    org.apache.commons
    commons-lang3
    3.7

このライブラリの最新バージョンはMaven Centralにあります。

3. プレーンJavaの使用

おそらく、String isが数値であるかどうかを確認する最も簡単で信頼性の高い方法は、Javaの組み込みメソッドを使用して解析することです。

  1. Integer.parseInt(String)

  2. Float.parseFloat(String)

  3. Double.parseDouble(String)

  4. Long.parseLong(String)

  5. 新しいBigInteger(String)

これらのメソッドがNumberFormatExceptionをスローしない場合は、解析が成功し、String isが数値であることを意味します。

public static boolean isNumeric(String strNum) {
    try {
        double d = Double.parseDouble(strNum);
    } catch (NumberFormatException | NullPointerException nfe) {
        return false;
    }
    return true;
}

このメソッドの動作を見てみましょう。

assertThat(isNumeric("22")).isTrue();
assertThat(isNumeric("5.05")).isTrue();
assertThat(isNumeric("-200")).isTrue();
assertThat(isNumeric("10.0d")).isTrue();
assertThat(isNumeric("   22   ")).isTrue();

assertThat(isNumeric(null)).isFalse();
assertThat(isNumeric("")).isFalse();
assertThat(isNumeric("abc")).isFalse();

isNumeric() メソッドでは、タイプDoubleの値をチェックするだけですが、このメソッドを変更して、IntegerFloatLong をチェックすることもできます。 )以前に参加した解析メソッドのいずれかを使用して、多数をサンドします。

これらのメソッドについては、Java String Conversions の記事でも説明されています。

3.1. Scannerを使用した入力の確認

java.utilScannerクラスは、プレーンJavaでintdoubleなどのプリミティブ型の入力を取得する最も簡単な方法です。 また、特定の入力が特定のタイプかどうかを検証するためのさまざまなAPIも提供します。

たとえば、the following APIs check whether the input is of type integer, long or float

  • scanner.hasNextInt()

  • scanner.hasNextLong()

  • scanner.hasNextFloat()

これらのAPIは、入力タイプに基づいて単純なtrueまたはfalseを返します。 これらのAPIを使用して、次の入力が目的のタイプであることを確認できます。

次のスニペットは、入力が整数かどうかをチェックします。

try (Scanner scanner = new Scanner(System.in)) {
    System.out.println("Enter an integer : ");
    if (scanner.hasNextInt()) {
        System.out.println("You entered : " + scanner.nextInt());
    } else {
        System.out.println("The input is not an integer");
    }
}

同様に、他のAPIを使用して他のタイプをチェックできます。

4. 正規表現を使用する

次に、正規表現-?\d+(\.\d+)?を使用して、正または負の整数と浮動小数点数で構成される数値Strings と一致させます。

しかし、これは言うまでもなく、この正規表現を間違いなく修正して、幅広いルールを識別し、対処することができます。 ここでは、簡単に説明します。

この正規表現を分解して、その仕組みを見てみましょう。

  • -? –この部分は、指定された数値が負であるかどうかを識別し、ダッシュ「」は文字通りダッシュを検索し、疑問符「?」はその存在をオプションとしてマークします

  • \d+ –これは1つ以上の数字を検索します

  • (\.\d+)? –正規表現のこの部分は、浮動小数点数を識別するためのものです。 ここでは、1つ以上の数字とそれに続くピリオドを検索しています。 最後に疑問符は、この完全なグループがオプションであることを示します

正規表現は非常に幅広いトピックです。簡単な概要を確認するには、this linked example articleにアクセスしてください。

とりあえず、上記の正規表現を使用してメソッドを作成しましょう。

public static boolean isNumeric(String strNum) {
    return strNum.matches("-?\\d+(\\.\\d+)?");
}

上記の方法のいくつかのアサーションを見てみましょう。

assertThat(isNumeric("22")).isTrue();
assertThat(isNumeric("5.05")).isTrue();
assertThat(isNumeric("-200")).isTrue();

assertThat(isNumeric("abc")).isFalse();

 5. Apache Commonsを使用する

このセクションでは、ApacheCommonsライブラリで利用できるさまざまなメソッドについて説明します。

5.1. NumberUtils.isCreatable(String)

Apache CommonsのNumberUtils は、 が有効なJava番号であるかどうかをチェックする静的メソッドNumberUtils.isCreatable(String) を提供します。

このメソッドは以下を受け入れます。

  1. 0xまたは0Xで始まる16進数

  2. 先行0で始まる8進数

  3. 科学表記法(1.05e-10など)

  4. 型修飾子でマークされた番号(1Lや2.2dなど)

指定された文字列がnull またはempty/blankの場合、それは数値とは見なされず、この場合、このメソッドはfalse を返します。

この方法を使用していくつかのテストを実行してみましょう。

assertThat(NumberUtils.isCreatable("22")).isTrue();
assertThat(NumberUtils.isCreatable("5.05")).isTrue();
assertThat(NumberUtils.isCreatable("-200")).isTrue();
assertThat(NumberUtils.isCreatable("10.0d")).isTrue();
assertThat(NumberUtils.isCreatable("1000L")).isTrue();
assertThat(NumberUtils.isCreatable("0xFF")).isTrue();
assertThat(NumberUtils.isCreatable("07")).isTrue();
assertThat(NumberUtils.isCreatable("2.99e+8")).isTrue();

assertThat(NumberUtils.isCreatable(null)).isFalse();
assertThat(NumberUtils.isCreatable("")).isFalse();
assertThat(NumberUtils.isCreatable("abc")).isFalse();
assertThat(NumberUtils.isCreatable(" 22 ")).isFalse();
assertThat(NumberUtils.isCreatable("09")).isFalse();

6、7、8行目でそれぞれ16進数、8進数、科学的記数法のtrue assertionsを取得していることに注意してください。

また、14行目では、文字列“09” false を返します。これは、前の“0” がこれが8進数であり、“09” が有効な8進数ではないことを示しているためです。

このメソッドでtrue を返すすべての入力に対して、有効な数を与えるNumberUtils.createNumber(String) を使用できます。

5.2. NumberUtils.isParsable(String)

NumberUtils.isParsable(String) メソッドは、指定されたString isが解析可能かどうかをチェックします。

解析可能な数値は、Integer.parseInt(String)Long.parseLong(String)Float.parseFloat(String) 、またはDouble.parseDouble(String)などの解析方法のいずれかによって正常に解析された数値です。

NumberUtils.isCreatable()とは異なり、このメソッドは、16進数、科学的記数法、または型修飾子で終わる文字列を受け入れません。 ‘f', ‘F', ‘d' ,'D' ,'l'or_‘L '._

いくつかの断言を見てみましょう:

assertThat(NumberUtils.isParsable("22")).isTrue();
assertThat(NumberUtils.isParsable("-23")).isTrue();
assertThat(NumberUtils.isParsable("2.2")).isTrue();
assertThat(NumberUtils.isParsable("09")).isTrue();

assertThat(NumberUtils.isParsable(null)).isFalse();
assertThat(NumberUtils.isParsable("")).isFalse();
assertThat(NumberUtils.isParsable("6.2f")).isFalse();
assertThat(NumberUtils.isParsable("9.8d")).isFalse();
assertThat(NumberUtils.isParsable("22L")).isFalse();
assertThat(NumberUtils.isParsable("0xFF")).isFalse();
assertThat(NumberUtils.isParsable("2.99e+8")).isFalse();

4行目では、NumberUtils.isCreatable()とは異なり、文字列“0” で始まる数値は、8進数ではなく、通常の10進数と見なされるため、trueを返します。

このメソッドは、セクション3で行ったことの代わりとして使用できます。セクション3では、数値を解析してエラーをチェックしようとしています。

5.3. StringUtils.isNumeric(CharSequence)

メソッドStringUtils.isNumeric(CharSequence) は、Unicode桁を厳密にチェックします。 これの意味は:

  1. Unicode数字である任意の言語の数字を使用できます

  2. 小数点はUnicode桁とは見なされないため、無効です

  3. 先行符号(正または負)も受け入れられません

このメソッドの動作を見てみましょう。

assertThat(StringUtils.isNumeric("123")).isTrue();
assertThat(StringUtils.isNumeric("١٢٣")).isTrue();
assertThat(StringUtils.isNumeric("१२३")).isTrue();

assertThat(StringUtils.isNumeric(null)).isFalse();
assertThat(StringUtils.isNumeric("")).isFalse();
assertThat(StringUtils.isNumeric("  ")).isFalse();
assertThat(StringUtils.isNumeric("12 3")).isFalse();
assertThat(StringUtils.isNumeric("ab2c")).isFalse();
assertThat(StringUtils.isNumeric("12.3")).isFalse();
assertThat(StringUtils.isNumeric("-123")).isFalse();

2行目と3行目の入力パラメータは、それぞれアラビア語とデーバナーガリー語の数値123 を表していることに注意してください。 これらは有効なUnicode桁であるため、このメソッドはそれらに対してtrue を返します。

5.4. StringUtils.isNumericSpace(CharSequence)

StringUtils.isNumericSpace(CharSequence) は、Unicodeの数字やスペースを厳密にチェックします。 これはStringUtils.isNumeric() と同じですが、スペースも受け入れることだけが異なります。先頭と末尾のスペースだけでなく、数字の間にある場合も同様です。

assertThat(StringUtils.isNumericSpace("123")).isTrue();
assertThat(StringUtils.isNumericSpace("١٢٣")).isTrue();
assertThat(StringUtils.isNumericSpace("")).isTrue();
assertThat(StringUtils.isNumericSpace("  ")).isTrue();
assertThat(StringUtils.isNumericSpace("12 3")).isTrue();

assertThat(StringUtils.isNumericSpace(null)).isFalse();
assertThat(StringUtils.isNumericSpace("ab2c")).isFalse();
assertThat(StringUtils.isNumericSpace("12.3")).isFalse();
assertThat(StringUtils.isNumericSpace("-123")).isFalse();

6. ベンチマーク

この記事を締めくくる前に、上記の方法のどれが最適なアプローチであるかを分析するのに役立つベンチマーク結果を簡単に見ていきましょう。

Benchmark                                     Mode   Cnt    Score     Error  Units
Benchmarking.usingCoreJava                    avgt   20   152.061 ±  24.300  ns/op
Benchmarking.usingRegularExpressions          avgt   20  1299.258 ± 175.688  ns/op
Benchmarking.usingNumberUtils_isCreatable     avgt   20    63.811 ±   5.638  ns/op
Benchmarking.usingNumberUtils_isParsable      avgt   20    58.706 ±   5.299  ns/op
Benchmarking.usingStringUtils_isNumeric       avgt   20    35.599 ±   8.498  ns/op
Benchmarking.usingStringUtils_isNumericSpace  avgt   20    37.010 ±   4.394  ns/op

ご覧のとおり、最もコストのかかる操作は正規表現を使用し、その後にコアJavaベースのソリューションを使用することです。 Apache Commonsライブラリを使用する他のすべての操作は、ほぼ同じです。

7. 結論

この記事では、String isが数値であるかどうかを確認するさまざまな方法について説明しました。 組み込みのメソッドと外部ライブラリの両方のソリューションを検討しました。

いつものように、ベンチマークの実行に使用されるコードを含む、上記のすべての例とコードスニペットの実装は、over on GitHubで見つけることができます。