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

1前書き

_Stringを操作している間、 _ Stringが有効な数値かどうかを判断する必要があります。

  • このチュートリアルでは、与えられた __String __が数値** であるかどうかを検出する複数の方法を探ります。最初に普通のJavaを使い、次に正規表現を使い、最後に外部ライブラリを使います。

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

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

2前提条件

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

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.7</version>
</dependency>

このライブラリの最新版はhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22org.apache.commons%22%20AND%20a%3A%22commons-lang3にあります。 %22[メイヴン中央]。

3プレーンJava の使い方

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

  1. Integer.parseInt(String)

  2. Float.parseFloat(String)

  3. Double.parseDouble(String)

  4. Long.parseLong(String)

  5. new 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 型の値をチェックしているだけですが、このメソッドは、先ほど紹介した解析メソッドのいずれかを使用して、 Integer Float Long _ 、および多数の値をチェックするように変更できます。

これらのメソッドは Java文字列変換 の記事でも議論されています。

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

java.util 's Scanner クラスは、おそらく int double などの基本タイプの入力を取得するためのプレーンJavaでの最も簡単な方法です。また、指定された入力が特定のタイプかどうかを検証するさまざまなAPIも提供します。

たとえば、** 次のAPIは、入力が整数型、long型、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 +)? __を使って、数値と一致させることができます。

しかし、これは言うまでもありませんが、この正規表現を修正して広範囲のルールを識別して対処することができます。ここでは、単純にします。

この正規表現を分解して、それがどのように機能するのかを見てみましょう。

  • -? - この部分は与えられた数が負であるかどうかを識別する、ダッシュ

”は文字通りダッシュを検索し、疑問符“ ”はそのダッシュをマークします。 オプションとして存在 ** \ d + - これは1桁以上の数字を検索します

  • (\。\ d)? - 正規表現のこの部分は浮動小数点数を識別するためのものです。ここに

1桁以上の数字とそれに続くピリオドを検索しています。最後の疑問符は、この完全なグループがオプションであることを意味します。

正規表現は非常に広いトピックであり、簡単な概要を得るためにリンクを見てください:/regular-expressions-java[このリンクされたBaeldungの記事]。

今のところ、上記の正規表現を使ってメソッドを作成しましょう:

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を使う

このセクションでは、Apache Commonsライブラリで利用可能なさまざまな方法について説明します。

5.1. NumberUtils.isCreatable(String)

Apache Commonsの __https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html[NumberUtils] は、静的メソッド https://commons.apacheを提供します。 org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html#isCreatable-java.lang.String-[NumberUtils.isCreatable(String)] これは __有効なJava番号かそうではありません。

このメソッドは受け入れます:

  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進数、科学表記法について正しい____アサーションがあることに注意してください。

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

このメソッドで _true を返す入力ごとに、https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html#createNumber-java.langを使用できます.String - [ NumberUtils.createNumber(String)_ ]これで有効な番号がわかります。

5.2. NumberUtils.isParsable(String)

__https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/math/NumberUtils.html#isParsable-java.lang.String-[NumberUtils.isParsable(String)] メソッド与えられた String __が解析可能かどうかをチェックします。

  • 解析可能な数値は、 Integer.parseInt(String) Long.parseLong(String) __Float.parseFloat(String) または Double.parseDouble(String)__のような任意の解析方法で正常に解析されたものです。

NumberUtils.isCreatable() とは異なり、このメソッドは16進数、科学表記法、または型修飾子で終わる文字列、つまり _ 'f'、 'F'、 'd'、 'D'、 'l’または 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で行ったことの代わりとして使用できます。ここでは、数値を解析してエラーをチェックします。

5.3. _StringUtils.isNumeric(CharSequence )___

メソッド __https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isNumeric-java.lang.CharSequence-[StringUtils.isNumeric(CharSequence)] __は厳密にチェックUnicode数字の場合これの意味は:

  1. Unicodeの数字である任意の言語の任意の数字が許容されます

  2. 小数点はUnicodeの数字とは見なされないので、

有効 。先行符号(正または負)もまた許容されません。

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

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行目の入力パラメータは、それぞれアラビア語とDevanagariの __122で数値を表しています。これらは有効な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 __が数値かどうかを調べるためのさまざまな方法を調べました。私たちは両方の解決策 - 組み込みメソッドと外部ライブラリ - を調べました。

いつものように、ベンチマークを実行するために使用されるコードを含む上記のすべての例とコードスニペットの実装はhttps://github.com/eugenp/tutorials/tree/master/java-strings[over on GitHub]で見つけることができます。