Java String-문자열에 문자가 아닌 숫자 만 포함되어 있는지 확인


196

응용 프로그램 전체에로드 할 문자열이 있으며 숫자에서 문자 등으로 변경됩니다. if문자 또는 숫자가 포함되어 있는지 확인 하는 간단한 설명이 있지만 제대로 작동하지 않습니다. 다음은 스 니펫입니다.

String text = "abc"; 
String number; 

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

text변수에 문자가 포함되어 있지만 조건은로 반환됩니다 true. 앤드 &&두 조건이 될 것으로 평가 후면한다 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,}")또는 함께 노력 Pattern하고Matcher
기욤 폴렛

문자열에 10 진수 값만 있거나 정수 값만있을 수 있습니까?
pseudoramble

3
text.length ()> 2를 확인하는 이유는 무엇입니까? 이유가 뭐야?
Code Enthusiastic

1
@RedHatcc Pattern.matches("[a-zA-Z]+", text) == false는 다음과 같이 단순화 될 수 있습니다!Pattern.matches("[a-zA-Z]+", text)
SARose

2
Java 스트리밍 API boolean isNumeric = someString.chars().allMatch(x -> Character.isDigit(x));양식 Max MalyshPost 사용.
Yash December

답변:


356

숫자를 텍스트로 처리하려면 다음을 변경하십시오.

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

에:

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

문자열에 알파벳 문자 포함되어 있지 않은지 확인하는 대신 숫자 포함되어 있는지 확인하십시오 .

실제로 숫자 값을 사용하려면 아래에 설명 된대로 Integer.parseInt()또는 Double.parseDouble()다른 것을 사용하십시오 .


부수적으로 일반적으로 부울 값을 true또는 과 비교하는 것은 나쁜 습관으로 간주됩니다 false. if (condition)또는을 사용하십시오 if (!condition).


25
앵커 (예 :)를 추가하고 싶을 ^[0-9]+$경우 abc123def숫자로 간주됩니다.
ICR

10
나는 그것이 필요하다고 생각하지 않습니다. matches()처음부터 끝까지 완전히 일치하는 경우에만 true를 반환합니다.
Chthonic Project

4
"^-? \ d + \.? \ d * $"는 전체 문자열을 비교하며 유효한 숫자 (음수 및 소수 포함) 인 경우에만 일치합니다. 예를 들어 1, 10, 1.0, -1, -1.0 등과 일치하며 "1"과도 일치합니다. 어쨌든 종종 파싱 될 수 있습니다.

16
전화 할 필요가 없습니다 && (text.length() > 2). 정규식 패턴으로 모든 것을 확인할 수 있습니다 :if (text.matches("[0-9]{3,}")
ctomek

정수가 아닌 숫자의 쉼표 나 점은 어떻습니까?
nibbana

20

Apache Commons에서 NumberUtil.isCreatable (String str) 을 사용할 수도 있습니다.


4
나는 NumberUtil.isCreatable(String str)원래의 질문에서 요구하는 것에 사용 하는 것이 옳다고 생각하지 않습니다 . 예를 들어, 숫자포함 하더라도를 NumberUtil.isCreatable( "09" )반환 합니다 . false"09"
Abdull

14

이것이 내가하는 방법입니다.

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

$부분 일치 예를 방지 할 수 있습니다; 1B.


1
text.length() > 2부품이 필요하지 않으므로 적어도 하나의 숫자가 있는지 확인하기 위해 교체 ^[0-9]*$했습니다 ^[0-9]+$.
YB Cause

8

parseInt최소한 예외 처리가 필요하기 때문에 성능 측면 에서는 다른 솔루션보다 훨씬 나쁩니다.

jmh 테스트를 실행했으며 문자열을 사용하여 문자열을 반복하고 charAt문자를 경계 문자와 비교하는 것이 문자열에 숫자 만 포함되어 있는지 테스트하는 가장 빠른 방법 이라는 것을 알았습니다 .

JMH 테스트

테스트는 char 값 과 vs. char 값의 성능을 Character.isDigit비교 합니다.Pattern.matcher().matchesLong.parseLong

이러한 방식은 ASCII가 아닌 문자열과 +/- 기호가 포함 된 문자열에 대해 다른 결과를 생성 할 수 있습니다.

테스트 5 번의 워밍업 반복과 5 번의 테스트 반복 으로 처리량 모드에서 실행됩니다 ( 더 클수록 좋습니다 ).

결과

parseLong에 비해 거의 100 배 느린 isDigit첫 번째 테스트 부하.

## 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 일에 업데이트 됨

  • 추가 charAt배열을 만드는 대신 사용 IntStream하고 문자 코드를 사용 하는 경우를 두 개 더 추가하십시오.
  • 반복 테스트 사례에 대해 숫자가 아닌 숫자가 발견되면 즉시 중단 추가
  • 반복 테스트 사례의 빈 문자열에 대해서는 false를 반환

2018 년 2 월 23 일에 업데이트 됨

  • 스트림을 사용하지 않고 문자 값을 비교하는 테스트 케이스를 하나 더 추가하십시오 (가장 빠름).

1
toCharArray의 코드를 보면 char 배열을 할당하고 문자를 복사하는 것입니다 (비용이 많이들 수 있습니다). 인덱스와 charAt을 사용하여 문자열을 반복하면 더 빠를까요? Andy의 솔루션을 테스트에 추가 할 수 있다면 흥미로울 것입니다 : boolean isNum = text.chars (). allMatch (c-> c> = 48 && c <= 57)
Aldo 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

아파치 코 몬즈 랭 제공 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; } }
Leo

1

숫자를 얻을 수있는 시설이 많이 있습니다 StringJava s에서 그 반대도 마찬가지입니다. 정규 표현식 부분을 건너 뛰어 복잡한 부분을 피할 수도 있습니다.

예를 들어, 어떤 Double.parseDouble(String s)결과를 얻을 수 있는지 시도해 볼 수 있습니다. NumberFormatException문자열에서 적절한 값을 찾지 못하면를 던져야 합니다. 이 기술을 제안하는 것은 실제로 String숫자 유형으로 표시된 값을 사용할 수 있기 때문 입니다.


5
입력을 테스트하는 이유로 예외를 사용하는 것은 좋지 않을 수 있습니다. 예외는 큰 오버 헤드를 만듭니다.
Ofir Luzon

1
@OfirLuzon 나는 예외가 발생할 것으로 예상되는 사례를 처리하는 좋은 방법이 아니라는 데 동의합니다. 그러나 더 많은 컨텍스트가 없으면 성능 저하가 있는지 알기가 어렵다고 생각합니다.
pseudoramble

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 ()을 사용하십시오 . 문자열이 (또는 숫자 만 있다면 그건 바로 당신을 말해주지 A는 적절하게, 수). 더 긴 숫자 문자열을 처리해야하는 경우 문자열 을 허용하는 BigIntegerBigDecimal 스포츠 생성자 둘 다 . 이들의이 발생합니다 NumberFormatException이를 당신이 그것을 (당신은 물론, 선택 하나를 기반으로 통합 또는 10 진수)가 아닌 수를 전달하려고합니다. 또는 요구 사항에 따라 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
-negative 번호
-decimal 구분 contries에에서 다를 수 있습니다 ( '.'예 ','또는)
-sometimes 공백이나 쉼표와 같은 소위 천 단위 구분 기호를 사용할 수 있습니다 (예 : 12,324,1000.355).

응용 프로그램에서 필요한 모든 경우를 처리하려면주의해야하지만이 정규식은 일반적인 시나리오 (양수 / 음수 및 분수, 점으로 구분)를 다룹니다. ^ [-+]? \ d *.? \ d + $
For 테스트 하려면 regexr.com을 권장 합니다 .


0

Adam Bodrogi의 약간 수정 된 버전 :

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;
}
}

오늘 이것을 사용해야 했으므로 방금 수정 사항을 게시했습니다. 통화, 수천 개의 쉼표 또는 마침표 표기법 및 일부 유효성 검사가 포함됩니다. 다른 통화 표기법 (유로, 센트)은 포함하지 않으며 확인 쉼표는 세 번째 숫자입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.