1

質問は一般的なものですが、クエリを引き起こしたシナリオについて言及します。

シナリオ:

多数の文字列(特に数値)の分析に興味があります。したがって、私の最初の仕事は、数字以外の文字を 1 つでも含むものを除外することです。

これを行う簡単な方法は (Java で):

for (String val : stringArray){
   try{
     int num = Integer.parseInt(val);
     doSomething(num);
   }
   catch(NumberFormatException nfe){}
}

私が言及しなければならないもう 1 つの点は、配列内の純粋な数値の文字列は約 5% しかないということです。したがって、要するに、多くのキャッチが含まれます。

私が疑問に思っていたのは、これがデザインの観点から効率的な方法なのか、それとも同じことを行う別の方法を考えるべきなのかということでした。


回答に基づく結論:例外は確かに高価であり、それらを制御ステートメントの形式として使用することはあまり良い設計方法ではありません。したがって、可能な限り代替案を探してみてください。それでも例外がより明確/簡単に見える場合は、それを適切に文書化する必要があります。

4

4 に答える 4

2

文字列が数値かどうかをチェックする Java の標準的な方法は他にないため、ここで行うことは本質的に正しいものです。

プロファイリングでこの操作が長すぎることが判明した場合は、parseInt メソッドのように自分で実行することもできます、JVM は同じ最適化を実行できないため、お勧めしません。JVM が例外を処理するように大幅に最適化されており、この仕事を非常にうまく行っていることがわかります。

好奇心として、 Java でそれを行ういくつかの方法を次に示します。

http://rosettacode.org/wiki/Determine_if_a_string_is_numeric#Java

他の言語へのリンクがありますが、あなたのソリューションは標準的で慣用的なものであり、例のように書き直すことで大きな違いが見つかるとは思えません:

private static final boolean isNumeric(final String s) {
  if (s == null || s.isEmpty()) return false;
  for (int x = 0; x < s.length(); x++) {
    final char c = s.charAt(x);
    if (x == 0 && (c == '-')) continue;  // negative
    if ((c >= '0') && (c <= '9')) continue;  // 0 - 9
    return false; // invalid
  }
  return true; // valid
}

私の意見では、これを使用することは、時期尚早の最適化がコードの保守性を低下させる典型的なケースです。

于 2012-06-15T15:34:14.210 に答える
1

効率的ではありません。例外のスローが高価であると見なされる理由については、Web で多くのリソースを検索できます

残念ながら、Java にはそのようなユーティリティ メソッド OOTB (C# の tryParse など) は付属していません。文字列の文字を列挙し、 Character.isDigit メソッドを使用できます (検証と int への変換を絡み合わせることもできます)。

一部のフローの異常終了には、例外を使用する必要があります。例外を発生させる可能性のある操作を実行する場合、コスト、特に例外を処理するためのコードを節約するチェックを実行できるかどうかを常に検討する必要があります。たとえば、文字列を解析しようとする代わりに、文字列が数値であるかどうかを確認し、そうでないかどうかを通知する例外メカニズムに依存します。

于 2012-06-15T15:42:11.817 に答える
0

アプリケーションのより大きなコンテキストでは、あまり問題にならない可能性があります。このようなマイクロ最適化は、推測するのが困難です。

より良いアプローチは、コードをできるだけきれいに記述してから、パフォーマンスを測定し、ボトルネックが存在する場合はどこにあるかを確認することです。パフォーマンスが許容できない場合は、最大のボトルネックを見つけて、可能であればそれに対処してください。すすぎ、パフォーマンスが許容できるまで繰り返します。

問題は、問題がどこにあるのかを「知る」ほど賢い人は誰もいないということです。推測するのではなく、データを使用して最適化することをお勧めします。

あなたの場合、それはチェックされていない例外です。あなたはそれを無視することができますが、それは単一の悪い文字列があなたをループから吹き飛ばすことを意味します. キャッチをループ内に配置すると、数値解析に失敗して続行する入力文字列のごく一部を許容できます。

于 2012-06-15T15:34:45.910 に答える
0

数値のみの文字列をチェックする非例外ベースの方法は、正規表現を使用することです。例えば:

public static void main(String[] args) throws Exception {
    String[] array = {
            "abc",
            "123",
            "12A",
    };
    Pattern p = Pattern.compile("\\d*");
    for (String s: array) {
        Matcher m = p.matcher(s);
        if (m.matches()) {
            System.out.println(s);
        }
    }
}

例外ベースの処理はコストがかかる可能性があります。

正規表現も最速ではありません。

両方を試して、どちらが速いかを確認してください。

于 2012-06-15T15:38:16.110 に答える