Java文字列-文字列に文字のみではなく数字のみが含まれているかどうかを確認します


195

アプリケーション全体にロードする文字列があり、数字から文字などに変わります。if文字または数字が含まれているかどうかを確認する簡単なステートメントがありますが、何かが正しく機能していません。こちらがスニペットです。

String text = "abc"; 
String number; 

if (text.contains("[a-zA-Z]+") == false && text.length() > 2) {
    number = text; 
}

text変数には文字が含まれていますが、条件はとして返されtrueます。そして&&両方の条件があることを有するようにevalべきでtrue処理するためにnumber = text;

==============================

解決:

この質問へのコメントによって提供された次のコードを使用することで、これを解決することができました。他のすべての投稿も同様に有効です!

うまくいったのは最初のコメントからです。提供されているすべてのサンプルコードも有効であるようですが!

String text = "abc"; 
String number; 

if (Pattern.matches("[a-zA-Z]+", text) == false && text.length() > 2) {
    number = text; 
}

5
containsは入力として正規表現を取りません。使用すると、いずれかmatches("\\d{2,}")またはを試みるPatternMatcher
ギヨームのPolet

文字列に10進値または整数値のみを含めることができますか?
擬似

3
なぜtext.length()> 2をチェックしているのですか?どういう理由ですか?
コード熱狂的な2013

1
@RedHatcc Pattern.matches("[a-zA-Z]+", text) == falseは次のように簡略化できます!Pattern.matches("[a-zA-Z]+", text)
SARose 2017年

2
JavaストリーミングAPI boolean isNumeric = someString.chars().allMatch(x -> Character.isDigit(x));フォームMax MalyshPost を使用します。
Yash

回答:


354

数値をテキストとして処理する場合は、次のように変更します。

if (text.contains("[a-zA-Z]+") == false && text.length() > 2){

に:

if (text.matches("[0-9]+") && text.length() > 2) {

文字列にアルファベット文字が含まれていないことを確認する代わりに、数字のみが含まれていることを確認してください。

実際に数値を使用したい場合は、Integer.parseInt()またはを使用して、Double.parseDouble()以下で説明します。


補足として、ブール値をtrueまたはと比較することは一般的に悪い習慣と見なされていますfalseif (condition)またはを使用してくださいif (!condition)


25
おそらくアンカー(例:)を追加する必要があります。^[0-9]+$そうしないabc123defと、数値と見なされます。
ICR 2013

10
それは必須ではないと思います。matches()最初から最後まで完全に一致した場合にのみtrueを返します。
Chthonicプロジェクト

4
"^-?\ d + \。?\ d * $"は文字列全体を比較し、それが有効な数値(負と10進数を含む)である場合にのみ一致します。たとえば、1、10、1.0、-1、-1.0などと一致します。「1」でも一致します。とにかく、それはしばしばとにかく解析することができます。

16
を呼び出す必要はありません&& (text.length() > 2)。すべてを正規表現パターンでチェックできます:if (text.matches("[0-9]{3,}")
ctomek '26

整数ではない数値のコンマやドットはどうですか?
nibbana


14

これは私がそれをする方法です:

if(text.matches("^[0-9]*$") && text.length() > 2){
    //...
}

$部分一致などを避けることができます。1B


1
text.length() > 2パーツは必要ないので、少なくとも1つの番号があることを確認^[0-9]*$するために交換し^[0-9]+$ました。
YBコーズ

8

parseInt少なくとも例外処理が必要なため、パフォーマンス面などは他のソリューションよりもはるかに劣ります。

私はjmhテストを実行しましたが、文字を使用charAtして文字を境界文字と比較することは、文字列に数字のみが含まれているかどうかをテストする最も速い方法であることがわかりました。

JMHテスト

テストは性能比較Character.isDigitPattern.matcher().matchesLong.parseLongchar型の値をチェックする対を。

これらの方法は、非ASCII文字列と+/-記号を含む文字列に対して異なる結果を生成する可能性があります。

テスト 5回のウォームアップ反復と5回のテスト反復でスループットモード(大きいほど良い)で実行されます。

結果

parseLongisDigit、最初のテストロードよりもほぼ100倍遅いことに注意してください。

## Test load with 25% valid strings (75% strings contain non-digit symbols)

Benchmark       Mode  Cnt  Score   Error  Units
testIsDigit    thrpt    5  9.275 ± 2.348  ops/s
testPattern    thrpt    5  2.135 ± 0.697  ops/s
testParseLong  thrpt    5  0.166 ± 0.021  ops/s

## Test load with 50% valid strings (50% strings contain non-digit symbols)

Benchmark              Mode  Cnt  Score   Error  Units
testCharBetween       thrpt    5  16.773 ± 0.401  ops/s
testCharAtIsDigit     thrpt    5  8.917 ± 0.767  ops/s
testCharArrayIsDigit  thrpt    5  6.553 ± 0.425  ops/s
testPattern           thrpt    5  1.287 ± 0.057  ops/s
testIntStreamCodes    thrpt    5  0.966 ± 0.051  ops/s
testParseLong         thrpt    5  0.174 ± 0.013  ops/s
testParseInt          thrpt    5  0.078 ± 0.001  ops/s

テストスイート

@State(Scope.Benchmark)
public class StringIsNumberBenchmark {
    private static final long CYCLES = 1_000_000L;
    private static final String[] STRINGS = {"12345678901","98765432177","58745896328","35741596328", "123456789a1", "1a345678901", "1234567890 "};
    private static final Pattern PATTERN = Pattern.compile("\\d+");

    @Benchmark
    public void testPattern() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                b = PATTERN.matcher(s).matches();
            }
        }
    }

    @Benchmark
    public void testParseLong() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                try {
                    Long.parseLong(s);
                    b = true;
                } catch (NumberFormatException e) {
                    // no-op
                }
            }
        }
    }

    @Benchmark
    public void testCharArrayIsDigit() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                for (char c : s.toCharArray()) {
                    b = Character.isDigit(c);
                    if (!b) {
                        break;
                    }
                }
            }
        }
    }

    @Benchmark
    public void testCharAtIsDigit() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                for (int j = 0; j < s.length(); j++) {
                    b = Character.isDigit(s.charAt(j));
                    if (!b) {
                        break;
                    }
                }
            }
        }
    }

    @Benchmark
    public void testIntStreamCodes() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                b = s.chars().allMatch(c -> c > 47 && c < 58);
            }
        }
    }

    @Benchmark
    public void testCharBetween() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                for (int j = 0; j < s.length(); j++) {
                    char charr = s.charAt(j);
                    b = '0' <= charr && charr <= '9';
                    if (!b) {
                        break;
                    }
                }
            }
        }
    }
}

2018年2月23日に更新

  • さらに2つのケースを追加-1つcharAtは追加の配列を作成する代わりに使用し、もう1つIntStreamは文字コードを使用する
  • ループしたテストケースで数字以外が見つかった場合、すぐにブレークを追加
  • ループしたテストケースの空の文字列に対してfalseを返す

2018年2月23日に更新

  • ストリームを使用せずにchar値を比較するテストケースをもう1つ追加(最速!)

1
toCharArrayのコードを見ると、char配列が割り当てられ、charがコピーされています(コストがかかる可能性があると思います)。インデックスとcharAtを使用して文字列を反復するだけの場合はどうでしょうか?あなたが試験にアンディのソリューションを追加することができる場合も興味深いものになるだろう:ブールisNum = text.chars()allMatch(C - > C> = 48 && C <= 57)
アルド・Canepa

8

ALPHABETSのみが含まれている文字列を簡単に確認するには、次のコードを使用します。

if (text.matches("[a-zA-Z]+"){
   // your operations
}

NUMBERのみが含まれている文字列を確認するには、次のコードを使用します。

if (text.matches("[0-9]+"){
   // your operations
}

これが誰かに役立つことを願っています!


3

ブールisNum = text.chars()。allMatch(c-> c> = 48 && c <= 57)


1
次のようにマジックナンバーを減らすために、あなたは、比較可能性:boolean isNum = text.chars().allMatch(c -> c >= '0' && c <= '9')
Phe0nix

2

あなたはRegex.Matchを使うことができます

if(text.matches("\\d*")&& text.length() > 2){
    System.out.println("number");
}

それとも、のようなonversions使用することができInteger.parseInt(String)たり、より良いLong.parseLong(String)例のような大きな数字のために:

private boolean onlyContainsNumbers(String text) {
    try {
        Long.parseLong(text);
        return true;
    } catch (NumberFormatException ex) {
        return false;
    }
} 

そして、次でテストします:

if (onlyContainsNumbers(text) && text.length() > 2) {
    // do Stuff
}

.matches( "^ \\ D + $")
CrandellWS

2

以下の正規表現を使用して、文字列に数値のみがあるかどうかを確認できます。

if (str.matches(".*[^0-9].*")) or if (str.matches(".*\\D.*"))

上記の両方の条件はtrue、文字列に非数値が含まれている場合に返されます。でfalse、文字列が数字のみを持っています。


2

Apache Commons Langはを提供しますorg.apache.commons.lang.StringUtils.isNumeric(CharSequence cs)。これは引数aを取り、それがString純粋な数値文字(非ラテン文字の数字を含む)で構成されているかどうかをチェックします。このメソッドはfalse、スペース、マイナス、プラスなどの文字、およびカンマやドットなどの小数点記号がある場合に戻ります。

そのクラスの他のメソッドは、さらなる数値チェックを可能にします。


1
これは正規表現よりもはるかに高速です。ここでの実装があります: public static boolean isNumeric(String str) { if (str == null) { return false; } else { int sz = str.length(); for(int i = 0; i < sz; ++i) { if (!Character.isDigit(str.charAt(i))) { return false; } } return true; } }
レオ

1

StringJavaのから数値を取得する機能はたくさんあります(逆も同様です)。正規表現の部分をスキップして、複雑さを解消することもできます。

たとえば、何Double.parseDouble(String s)が戻ってくるかを試してみることができます。NumberFormatException文字列で適切な値が見つからない場合は、スローする必要があります。実際にで表される値をString数値型として利用できるため、この手法をお勧めします。


5
入力をテストする理由として例外を使用するのは悪い考えかもしれませんが、例外は大きなオーバーヘッドを生み出します。
Ofir Luzon 2013

1
@OfirLuzon例外は、発生する予定のケースを処理するための優れた方法ではないことに同意します。ただし、コンテキストがなければパフォーマンスヒットが発生するかどうかを判断するのは難しいと思います。
2013年

1

これが私のコードです、これがあなたを助けることを願っています!

 public boolean isDigitOnly(String text){

    boolean isDigit = false;

    if (text.matches("[0-9]+") && text.length() > 2) {
        isDigit = true;
    }else {
        isDigit = false;
    }

    return isDigit;
}

0

このコードはすでに書かれています。(非常に)小さなパフォーマンスヒットを気にしない場合(おそらく正規表現の一致よりも悪いことではありませんInteger.parseInt()またはDouble.parseDouble()を使用します。文字列が数値のみ(または必要に応じて数値)である場合は、すぐにわかります。長い数値の文字列を処理する必要がある場合は、BigIntegerBigDecimalの両方のスポーツコンストラクターで文字列を受け入れます。これらに非数値(もちろん、選択したものに基づく整数または10進数)を渡そうとすると、NumberFormatExceptionがスローされます。または、要件に応じて、String内の文字を反復処理し、Character.isDigit()を確認しますおよび/またはCharacter.isLetter()


0
import java.util.*;

class Class1 {
    public static void main(String[] argh) {
        boolean ans = CheckNumbers("123");
        if (ans == true) {
            System.out.println("String contains numbers only");
        } else {
            System.out.println("String contains other values as well");

        }
    }


    public static boolean CheckNumbers(String input) {
        for (int ctr = 0; ctr < input.length(); ctr++) {
            if ("1234567890".contains(Character.valueOf(input.charAt(ctr)).toString())) {
                continue;
            } else {
                return false;
            }
        }
        return true;
    }
}

0
Character first_letter_or_number = query.charAt(0);
                //------------------------------------------------------------------------------
                if (Character.isDigit())
                {

                }
                else if (Character.isLetter())
                {

                }

0

実用試験例

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

public class PaserNo {

    public static void main(String args[]) {

        String text = "gg";

        if (!StringUtils.isBlank(text)) {
            if (stringContainsNumber(text)) {
                int no=Integer.parseInt(text.trim());
                System.out.println("inside"+no);

            } else {
                System.out.println("Outside");
            }
        }
        System.out.println("Done");
    }

    public static boolean stringContainsNumber(String s) {
        Pattern p = Pattern.compile("[0-9]");
        Matcher m = p.matcher(s);
        return m.find();
    }
}

それでも、コードが「1a」などで区切られる可能性があるため、例外を確認する必要があります

if (!StringUtils.isBlank(studentNbr)) {
                try{
                    if (isStringContainsNumber(studentNbr)){
                    _account.setStudentNbr(Integer.parseInt(studentNbr.trim()));
                }
                }catch(Exception e){
                    e.printStackTrace();
                    logger.info("Exception during parse studentNbr"+e.getMessage());
                }
            }

いいえをチェックする方法は文字列かどうか

private boolean isStringContainsNumber(String s) {
        Pattern p = Pattern.compile("[0-9]");
        Matcher m = p.matcher(s);
        return m.find();
    }

0

このような典型的なシナリオに例外のスロー/処理を含めることは悪い習慣です。

そのためのparseInt()は素敵ではありませんが、正規表現は、このためのエレガントな解決策であるが、以下の世話をする:
-fractions
陰性番号
-decimalセパレータはcontriesに異なる場合があります(「」たとえば「」または)
-sometimesスペースやコンマのように、いわゆる1000の区切り文字を使用できます。たとえば、12,324,1000.355

アプリケーションで必要なすべてのケースを処理するには注意する必要がありますが、この正規表現は一般的なシナリオ(正/負および小数、ドットで区切られたもの)をカバーしています:^ [-+]?\ d *。?\ d + $
Forテスト、私はregexr.comをお勧めします


0

アダムボドロギのわずかに変更されたバージョン:

public class NumericStr {


public static void main(String[] args) {
    System.out.println("Matches: "+NumericStr.isNumeric("20"));         // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("20,00"));          // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("30.01"));          // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("30,000.01"));          // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("-2980"));          // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("$20"));            // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("jdl"));            // Should be false
    System.out.println("Matches: "+NumericStr.isNumeric("2lk0"));           // Should be false
}

public static boolean isNumeric(String stringVal) {
    if (stringVal.matches("^[\\$]?[-+]?[\\d\\.,]*[\\.,]?\\d+$")) {
        return true;
    }

    return false;
}
}

今日これを使用しなければならなかったので、私の変更を投稿しました。通貨、千単位のコンマまたはピリオド表記、およびいくつかの検証が含まれています。他の通貨表記(ユーロ、セント)は含まれません。検証カンマは3桁ごとです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.