あえて言うほどではない 数値変換時の型チェック Java編

こんにちはJavaプログラマなうの村上です。

今回は数値変換時の型チェックに関する記事です。

以前数値 ⇔ 文字列変換で文字列を数値変換する時は

とかで数値変換するようなコードを書いてましたが、だいたい数値変換する時は数値変換可能かのバリデーションをするのがお行儀が良いです。
なので、今回は数値変換時のバリデーションについて

型チェックの方法は色々あるとおもいますが、次の3つで検証してみました。

  1. Integer#parseInt()時の例外チェック
  2. 正規表現チェック
  3. commons-langのNumberUtils#isNumber()

(注意)

  • 今回は整数時のチェックのみということにしています。
  • 正規表現のチェックの実際のコードはPatternオブジェクトをインスタンス変数にしてオブジェクト生成のコストを下げています。

100万回のループですべてtrueを返すもの場合(文字列の1とか)とすべてfalseを返す場合(文字列のaとか)で調査しました。
以下結果です。単位はミリ秒です。

Java5 Java6 Java7
Integer#parseInt() すべてtrue 292 218 183
すべてfalse 1739 1329 1051
正規表現チェック すべてtrue 532 455 291
すべてfalse 515 455 273
NumberUtils#isNumber() すべてtrue 212 180 159
すべてfalse 212 187 128

Integer#parseInt()はtrueを返す場合とfalseを返す場合でずいぶんと差がでますね。
エラー時は例外クラスを生成してスローするので遅くなりそうな感じがしますね。
正規表現チェックとNumberUtils#isNumber()はどちらも安定していますね。

ただ今回は整数に限ってなのでご注意を!!
ちなみに次の文字列でそれぞれが返す値は以下の通りです。

ケース Integer#parseInt() 正規表現チェック NumberUtils#isNumber()
1 true true true
123 true true true
a false false false
0 true true true
-100 true true true
10-10 false false false
+100 true false false
10+10 false false false
+ false false false
- false false false
1.0 false false true
1.1 false false true
1,000 false false false
12345678901234567890 false true true
0x123 false false true
123L false false true
123D false false true
12e3 false false true

※ 網掛け部分を追記(2014年5月22日)
今回は整数のみということなので、16進数、long型、小数点などの表記方法では結果が異なります。
開発時には注意を!!!

Comments are closed, but you can leave a trackback: Trackback URL.

Comments

  • 老害  On 2014年5月14日 at 17:36

    3の例は1と2とは同じ結果を返しません

    System.out.println(NumberUtils.isNumber("0x123"));

    System.out.println(NumberUtils.isNumber("123L"));

    System.out.println(NumberUtils.isNumber("123D"));

    System.out.println(NumberUtils.isNumber("12e3"));

    • 村上 直広  On 2014年5月22日 at 17:31

      ご指摘ありがとうございます。
      今回のエントリーは整数に限定させております。
      良いご指摘でしたので、一覧に追加させて頂きました!!

  • えーだぶ  On 2017年4月13日 at 19:45

    isNumberに"08000"を渡したらfalseになりました。なぜなのでしょう?

    • 村上 直広  On 2017年4月21日 at 11:29

      ご質問ありがとうございます。
      「0」から始まる場合は8進数として解釈され、8進数として正しくないのでfalseが返ります。