String이 Java에서 정수를 나타내는 지 확인하는 가장 좋은 방법은 무엇입니까?


214

나는 일반적으로 문자열을 정수로 변환 할 수 있는지 확인하기 위해 다음 관용구를 사용합니다.

public boolean isInteger( String input ) {
    try {
        Integer.parseInt( input );
        return true;
    }
    catch( Exception e ) {
        return false;
    }
}

그것은 단지 나입니까, 아니면 약간의 해킹처럼 보입니까? 더 좋은 방법은 무엇입니까?


내가 왜 내 입장을 바꾸었고이 문제에 대한 Jonas Klemming의 답변 을 받아들 였는지 알아 보려면 내 답변 ( CodingWithSpike이전 답변 을 기반으로 한 벤치 마크 포함 )을 참조하십시오 . 필자는이 원본 코드를 구현하는 것이 더 빠르고 유지 관리가 용이하기 때문에 대부분의 사람들이이 코드를 사용한다고 생각하지만 정수가 아닌 데이터가 제공되면 수십 배 느립니다.


솔루션의 RegExp에 대해 어떻게 생각하십니까?
Akshay Pethani

답변:


171

잠재적 오버플로 문제에 대해 걱정하지 않으면이 기능은을 사용하는 것보다 약 20-30 배 더 빠르게 수행됩니다 Integer.parseInt().

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    if (length == 0) {
        return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
        if (length == 1) {
            return false;
        }
        i = 1;
    }
    for (; i < length; i++) {
        char c = str.charAt(i);
        if (c < '0' || c > '9') {
            return false;
        }
    }
    return true;
}

50
(c <= '/'|| c> = ':')는 조금 이상하게 보입니다. (c < '0'|| c> '9')를 사용했을 것입니다 ... Java에서 <= 및> = 연산자가 더 빠릅니까?
Anonymous

3
왜 정규식을 사용하지 않습니까? str.matches ( "^-? \\ d + $")는 위의 코드와 동일하지 않습니다.
Maglob

15
정규식 전에 질문 에서이 방법이나 원래 방법을 사용합니다. 이는 구현 속도와 완벽한 유지 관리를위한 원래의 방법 인 성능을위한 것입니다. 정규식 솔루션에는 아무런 효과가 없습니다.
Bill the Lizard

4
오버플로가 걱정되지만이 방법을 BigInts에 적용 할 수 있으며 다른 방법보다 훨씬 빠릅니다. 왜 내가 그렇게 간단한 문제에 많은 노력을 기울이고 있는지 궁금해하는 경우 Project Euler 문제를 해결하는 데 도움이되는 라이브러리를 만들고 있습니다.
Bill the Lizard

1
실제로 문자열을 int 또는 long으로 구문 분석 할 수 있는지 염려되면 문자열이 나타내는 정수가 실제로 해당 데이터 유형에 맞는지 확인해야합니다.
Jonas K

65

당신은 그것을 가지고 있지만, 당신은 잡아야 NumberFormatException합니다.


7
예, 필요한 것보다 더 많은 예외를 잡는 것은 나쁜 형태로 간주됩니다.
Chris

네가 옳아. NFE는 던져 질 수있는 유일한 것이지만 여전히 나쁜 습관입니다.
Bill the Lizard

입력이 null 인 경우 NPE가 throw 될 수 있으므로 메서드가 원하는 방식으로 명시 적으로 처리해야합니다.
Dov Wasserman

@Dov : 맞습니다. NPE와 NFE 모두 명시 적으로 파악해야합니다.
Bill the Lizard

이 답변은이 질문에 대한 진정한 답이어야합니다.
Breedly

40

빠른 벤치 마크를했습니다. 여러 메소드를 다시 시작하지 않고 JVM이 실행 스택을 가져 오기 위해 많은 작업을 수행하지 않는 한 실제로는 그렇게 많은 비용이 들지 않습니다. 같은 방법으로 머무를 때, 그들은 나쁜 수행자가 아닙니다.

 public void RunTests()
 {
     String str = "1234567890";

     long startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByException(str);
     long endTime = System.currentTimeMillis();
     System.out.print("ByException: ");
     System.out.println(endTime - startTime);

     startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByRegex(str);
     endTime = System.currentTimeMillis();
     System.out.print("ByRegex: ");
     System.out.println(endTime - startTime);

     startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByJonas(str);
     endTime = System.currentTimeMillis();
     System.out.print("ByJonas: ");
     System.out.println(endTime - startTime);
 }

 private boolean IsInt_ByException(String str)
 {
     try
     {
         Integer.parseInt(str);
         return true;
     }
     catch(NumberFormatException nfe)
     {
         return false;
     }
 }

 private boolean IsInt_ByRegex(String str)
 {
     return str.matches("^-?\\d+$");
 }

 public boolean IsInt_ByJonas(String str)
 {
     if (str == null) {
             return false;
     }
     int length = str.length();
     if (length == 0) {
             return false;
     }
     int i = 0;
     if (str.charAt(0) == '-') {
             if (length == 1) {
                     return false;
             }
             i = 1;
     }
     for (; i < length; i++) {
             char c = str.charAt(i);
             if (c <= '/' || c >= ':') {
                     return false;
             }
     }
     return true;
 }

산출:

예외 : 31

ByRegex : 453 (참고 : 매번 패턴을 다시 컴파일)

바이 조나스 : 16

Jonas K의 솔루션이 가장 강력하다는 데 동의합니다. 그가이기는 것 같습니다 :)


13
세 가지를 모두 벤치마킹하는 것이 좋습니다. Regex 및 Jonas 메서드에 공정하려면 Integer.parseInt 메서드가 실제로 느려질 수 있으므로 정수가 아닌 문자열로 테스트해야합니다.
Bill the Lizard

4
죄송하지만이 정규식 테스트는 좋지 않습니다. (1) 당신이 정규식 엔진 체크 할 필요가 없습니다 ^$의 이후 두 번째 matches정규 표현식 일치해야합니다 전체 문자열, (2) str.matches마다 자체 만들어야합니다 Pattern고가 인을. 성능상의 이유로이 메소드 외부에서 이러한 패턴을 한 번만 작성하고 내부에서 사용해야합니다. (3) 또한 하나의 Matcher 객체 만 생성하고이를 사용하여 reset(CharSequence)사용자 데이터를 전달하고 matches()결과를 반환 할 수 있습니다.
Pshemo

따라서 private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); }성능이 더 좋아야합니다.
Pshemo

@Pshemo Integer.valueOf ( "1") 및 Integer.valueOf ( "1") 모두 예외가 발생하므로 ^ 및 $를 확인하는 것이 합리적으로 보입니다.
cquezel

1
예 @cquezel,하지만하지 않습니다 필요 하기 때문에 matchesIS가 추가 ^$암시. " 123".matches("\\d+")및의 결과를 살펴보십시오 "123".matches("\\d+"). 당신은 볼 falsetrue. false문자열이 공백으로 시작하여 정규 표현식과 완전히 일치하지 못하게하기 때문에 반환됩니다.
Pshemo

37

사람들이 여전히 여기에 방문하여 벤치 마크 후에 Regex에 대해 편견을 가질 가능성이 있기 때문에 ... 그래서 컴파일 된 버전의 Regex로 벤치 마크의 업데이트 버전을 제공 할 것입니다. 이전 벤치 마크와 달리이 솔루션은 Regex 솔루션의 성능이 지속적으로 우수함을 보여줍니다.

Bill the Lizard에서 복사하고 컴파일 된 버전으로 업데이트했습니다.

private final Pattern pattern = Pattern.compile("^-?\\d+$");

public void runTests() {
    String big_int = "1234567890";
    String non_int = "1234XY7890";

    long startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(big_int);
    long endTime = System.currentTimeMillis();
    System.out.print("ByException - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByException - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByRegex - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByCompiledRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByCompiledRegex - non-integer data: ");
    System.out.println(endTime - startTime);


    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByJonas - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByJonas - non-integer data: ");
    System.out.println(endTime - startTime);
}

private boolean IsInt_ByException(String str)
{
    try
    {
        Integer.parseInt(str);
        return true;
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
}

private boolean IsInt_ByRegex(String str)
{
    return str.matches("^-?\\d+$");
}

private boolean IsInt_ByCompiledRegex(String str) {
    return pattern.matcher(str).find();
}

public boolean IsInt_ByJonas(String str)
{
    if (str == null) {
            return false;
    }
    int length = str.length();
    if (length == 0) {
            return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
            if (length == 1) {
                    return false;
            }
            i = 1;
    }
    for (; i < length; i++) {
            char c = str.charAt(i);
            if (c <= '/' || c >= ':') {
                    return false;
            }
    }
    return true;
}

결과 :

ByException - integer data: 45
ByException - non-integer data: 465

ByRegex - integer data: 272
ByRegex - non-integer data: 131

ByCompiledRegex - integer data: 45
ByCompiledRegex - non-integer data: 26

ByJonas - integer data: 8
ByJonas - non-integer data: 2

1
ByCompiledRegex 시간은 시간 측정에서 정규식 컴파일을 포함해야합니다.
Martin Carney

2
@MartinCarney 나는 그것을 수정하고 패턴 컴파일을 벤치마킹했다. 분명히 내 CPU / JIT가 빠르지 만 다시 보간하면 컴파일 시간은 336입니다.
tedder42

2
336 (ms)는 다른 모든 라인과 마찬가지로 패턴 컴파일이 100k 회 수행 될 때 발생하는 것입니다. 한 번만 수행된다는 의미로 시간은 기본적으로 0입니다.
tedder42

컴파일 된 정규식 시간에 레코드를 똑바로 설정해 주셔서 감사합니다.
LarsH

아마도 "^[+-]?\\d+$"더 나을 것입니다.
Adam

34
org.apache.commons.lang.StringUtils.isNumeric 

Java의 표준 lib는 실제로 그러한 유틸리티 기능을 그리워합니다.

Apache Commons는 모든 Java 프로그래머에게 "필수 사항"이라고 생각합니다

너무 나빠 아직 Java5로 포팅되지 않았습니다.


1
이것의 유일한 문제는 오버플로입니다 : SI는 여전히 commons-lang을 언급하면 ​​+1을줍니다 :)
javamonkey79

2
다른 문제는 음수이지만 +1도 있습니다. 내 관점 에서이 접근법은 좋은 솔루션에 가장 가깝기 때문입니다.
sandris

22

"정수로 변환 할 수 있습니다"라는 의미에 부분적으로 의존합니다.

"Java에서 int로 변환 할 수있다"는 것을 의미한다면 Jonas의 대답은 좋은 출발이지만 작업을 끝내지는 못합니다. 예를 들어 999999999999999999999999999999를 전달합니다. 메서드 끝에 자신의 질문에서 일반적인 try / catch 호출을 추가합니다.

문자 별 검사는 "정수가 아닌"경우를 효율적으로 거부하여 "정수이지만 Java가 처리 할 수 ​​없습니다"라는 경우를 제외하고 느린 예외 경로에 의해 포착됩니다. 당신은 할 수 너무 손이 비트를 할 수 있지만, 그것은 것 많이 더 복잡.


17

regexp에 대한 한 가지 의견. 여기에 제공된 모든 예가 잘못되었습니다!. regexp를 사용하려면 패턴을 컴파일하는 데 많은 시간이 걸린다는 것을 잊지 마십시오. 이:

str.matches("^-?\\d+$")

또한 이것 :

Pattern.matches("-?\\d+", input);

모든 메소드 호출에서 패턴을 컴파일합니다. 올바르게 사용하려면 다음을 수행하십시오.

import java.util.regex.Pattern;

/**
 * @author Rastislav Komara
 */
public class NaturalNumberChecker {
    public static final Pattern PATTERN = Pattern.compile("^\\d+$");

    boolean isNaturalNumber(CharSequence input) {
        return input != null && PATTERN.matcher(input).matches();
    }
}

5
Matcher를 미리 생성하고 reset () 메소드를 사용하여 입력에 적용하여 성능을 조금 더 향상시킬 수 있습니다.
Alan Moore

13

구아바 버전이 있습니다 :

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

문자열 구문 분석에 실패하면 예외를 throw하는 대신 null을 반환합니다.


3
최고의 답변 IMHO. 자체 솔루션을 롤업하는 대신 잘 테스트 된 라이브러리를 사용하십시오. (또한 토론을 참조 하십시오 .)
Olivier Cailloux

12

rally25rs 답변에서 코드를 복사하고 정수가 아닌 데이터에 대한 테스트를 추가했습니다. 이 결과는 Jonas Klemming이 게시 한 방법에 찬성합니다. 내가 처음 게시 한 Exception 메소드의 결과는 정수 데이터가있을 때 꽤 좋지만 Regex 솔루션에 대한 결과는 그렇지 않은 경우 최악입니다 (많은 사람들이 사용합니다) 했다 지속적으로 나쁜. 훨씬 빠른 컴파일 된 정규식 예제는 Felipe의 답변 을 참조하십시오 .

public void runTests()
{
    String big_int = "1234567890";
    String non_int = "1234XY7890";

    long startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByException(big_int);
    long endTime = System.currentTimeMillis();
    System.out.print("ByException - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByException(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByException - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByRegex - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByJonas(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByJonas - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByJonas(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByJonas - non-integer data: ");
    System.out.println(endTime - startTime);
}

private boolean IsInt_ByException(String str)
{
    try
    {
        Integer.parseInt(str);
        return true;
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
}

private boolean IsInt_ByRegex(String str)
{
    return str.matches("^-?\\d+$");
}

public boolean IsInt_ByJonas(String str)
{
    if (str == null) {
            return false;
    }
    int length = str.length();
    if (length == 0) {
            return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
            if (length == 1) {
                    return false;
            }
            i = 1;
    }
    for (; i < length; i++) {
            char c = str.charAt(i);
            if (c <= '/' || c >= ':') {
                    return false;
            }
    }
    return true;
}

결과 :

ByException - integer data: 47
ByException - non-integer data: 547

ByRegex - integer data: 390
ByRegex - non-integer data: 313

ByJonas - integer data: 0
ByJonas - non-integer data: 16

6

이것은 더 짧지 만 더 짧을 필요는 없습니다 ( 다나 텔의 주석에서 지적했듯이 범위를 벗어난 정수 값을 포착하지는 않습니다 ).

input.matches("^-?\\d+$");

개인적으로 구현이 도우미 메서드에서 쫓겨 나고 정확성이 길이를 능가하기 때문에 나는 당신이 가진 것과 같은 것을 가지고 갈 ExceptionNumberFormatException입니다.


1
그리고 아마도 \\ d {1,10}은 완벽하지는 않지만 Java 정수를 잡기 위해 \\ d +보다 낫습니다
Maglob

6

문자열 클래스의 matches 메소드를 사용할 수 있습니다. [0-9]는 가능한 모든 값을 나타내고 +는 최소 1 자 이상이어야하고 *는 0 자 이상일 수 있음을 의미합니다.

boolean isNumeric = yourString.matches("[0-9]+"); // 1 or more characters long, numbers only
boolean isNumeric = yourString.matches("[0-9]*"); // 0 or more characters long, numbers only

1
Nb 이것은 "+10"또는 "-10"과 일치하지 않습니다. 일반적으로 유효한 정수로 포함됩니다.
Tim Wintle

4

어때요?

return Pattern.matches("-?\\d+", input);

정수 9999999999999999999999999999999999는 어떻습니까?
danatel

음수 부호를 확인하는 것을 잊지 마십시오.
Jeremy Ruten

정규식의 시작과 끝을 정박시킬 필요가 없으므로 "aaa-1999zzz"를 전달하지 않습니까?
Tim Howland

2
Tim, matches () 메소드 중 하나를 호출하면 (문자열, 패턴 및 매처마다 하나씩) 정규식은 전체 입력과 일치해야하므로 앵커가 중복됩니다. 대부분의 다른 정규 표현식에 정의 된대로 일치 항목을 찾으려면 Matcher # find ()를 사용해야합니다.
Alan Moore

4

이것은 Jonas Klemming의 Java 8 변형입니다.

public static boolean isInteger(String str) {
    return str != null && str.length() > 0 &&
         IntStream.range(0, str.length()).allMatch(i -> i == 0 && (str.charAt(i) == '-' || str.charAt(i) == '+')
                  || Character.isDigit(str.charAt(i)));
}

테스트 코드 :

public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    Arrays.asList("1231231", "-1232312312", "+12313123131", "qwqe123123211", "2", "0000000001111", "", "123-", "++123",
            "123-23", null, "+-123").forEach(s -> {
        System.out.printf("%15s %s%n", s, isInteger(s));
    });
}

테스트 코드의 결과 :

        1231231 true
    -1232312312 true
   +12313123131 true
  qwqe123123211 false
              2 true
  0000000001111 true
                false
           123- false
          ++123 false
         123-23 false
           null false
          +-123 false

3

당신은 NumberFormatException을 확인합니다 :-

 String value="123";
 try  
 {  
    int s=Integer.parseInt(any_int_val);
    // do something when integer values comes 
 }  
 catch(NumberFormatException nfe)  
 {  
          // do something when string values comes 
 }  

3

String 배열에 순수한 정수 및 문자열이 포함되어 있으면 아래 코드가 작동합니다. 첫 문자 만 봐야합니다. 예를 들어 [ "4", "44", "abc", "77", "bond"]

if (Character.isDigit(string.charAt(0))) {
    //Do something with int
}

3

또한 Scanner 클래스를 사용하고 hasNextInt ()를 사용할 수 있습니다. 이렇게하면 float 등과 같은 다른 유형도 테스트 할 수 있습니다.


이 대답은 내가 필요한 알림을 주었다. 스캐너가 그런 기능을 가지고 있다는 것을 완전히 잊었습니다. T-up
Hubro

2

문자열이 int 유형에 맞는 정수를 나타내는 지 확인하려면 jonas의 대답을 약간 수정하여 Integer.MAX_VALUE보다 크거나 Integer.MIN_VALUE보다 작은 정수를 나타내는 문자열을 반환합니다. 그릇된. 예를 들어 : 3147483647이 2147483647보다 커서 "3147483647"은 false를 반환하고 마찬가지로 -2147483649가 -2147483648보다 작기 때문에 "-2147483649"도 false를 반환합니다.

public static boolean isInt(String s) {
  if(s == null) {
    return false;
  }
  s = s.trim(); //Don't get tricked by whitespaces.
  int len = s.length();
  if(len == 0) {
    return false;
  }
  //The bottom limit of an int is -2147483648 which is 11 chars long.
  //[note that the upper limit (2147483647) is only 10 chars long]
  //Thus any string with more than 11 chars, even if represents a valid integer, 
  //it won't fit in an int.
  if(len > 11) {
    return false;
  }
  char c = s.charAt(0);
  int i = 0;
  //I don't mind the plus sign, so "+13" will return true.
  if(c == '-' || c == '+') {
    //A single "+" or "-" is not a valid integer.
    if(len == 1) {
      return false;
    }
    i = 1;
  }
  //Check if all chars are digits
  for(; i < len; i++) {
    c = s.charAt(i);
    if(c < '0' || c > '9') {
      return false;
    }
  }
  //If we reached this point then we know for sure that the string has at
  //most 11 chars and that they're all digits (the first one might be a '+'
  // or '-' thought).
  //Now we just need to check, for 10 and 11 chars long strings, if the numbers
  //represented by the them don't surpass the limits.
  c = s.charAt(0);
  char l;
  String limit;
  if(len == 10 && c != '-' && c != '+') {
    limit = "2147483647";
    //Now we are going to compare each char of the string with the char in
    //the limit string that has the same index, so if the string is "ABC" and
    //the limit string is "DEF" then we are gonna compare A to D, B to E and so on.
    //c is the current string's char and l is the corresponding limit's char
    //Note that the loop only continues if c == l. Now imagine that our string
    //is "2150000000", 2 == 2 (next), 1 == 1 (next), 5 > 4 as you can see,
    //because 5 > 4 we can guarantee that the string will represent a bigger integer.
    //Similarly, if our string was "2139999999", when we find out that 3 < 4,
    //we can also guarantee that the integer represented will fit in an int.
    for(i = 0; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if(c > l) {
        return false;
      }
      if(c < l) {
        return true;
      }
    }
  }
  c = s.charAt(0);
  if(len == 11) {
    //If the first char is neither '+' nor '-' then 11 digits represent a 
    //bigger integer than 2147483647 (10 digits).
    if(c != '+' && c != '-') {
      return false;
    }
    limit = (c == '-') ? "-2147483648" : "+2147483647";
    //Here we're applying the same logic that we applied in the previous case
    //ignoring the first char.
    for(i = 1; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if(c > l) {
        return false;
      }
      if(c < l) {
        return true;
      }
    }
  }
  //The string passed all tests, so it must represent a number that fits
  //in an int...
  return true;
}

1
답변을 수정하고 이전 답변이 어떻게 개선되는지 설명해 주시겠습니까?
Gilles Gouaillardet '

큰 답변 주셔서 감사합니다. 그러나 "123", 즉 공백과 함께 123은 유효한 정수로 간주됩니다.
Saikrishna Radarapu

1
@SaikrishnaRadarapu 그들은 trim()의도적으로 의도 된 디자인 선택을 위해 사용 합니다.
Guildenstern


1

유스 케이스도 고려해야합니다.

대부분의 경우 숫자가 유효 할 것으로 예상되는 경우 예외를 포착하면 유효하지 않은 숫자를 변환하려고 할 때 성능 오버 헤드 만 발생합니다. 일부 isInteger()메소드를 호출 한 다음 사용하여 변환 Integer.parseInt()하면 항상 유효한 숫자에 대한 성능 오버 헤드가 발생하지만 문자열은 확인으로 한 번, 변환으로 한 번 두 번 구문 분석됩니다.


1

이것은 문자열이 정수로 캐스트 될 범위 내에 있는지 확인하는 Jonas 코드 의 수정입니다 .

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    int i = 0;

    // set the length and value for highest positive int or lowest negative int
    int maxlength = 10;
    String maxnum = String.valueOf(Integer.MAX_VALUE);
    if (str.charAt(0) == '-') { 
        maxlength = 11;
        i = 1;
        maxnum = String.valueOf(Integer.MIN_VALUE);
    }  

    // verify digit length does not exceed int range
    if (length > maxlength) { 
        return false; 
    }

    // verify that all characters are numbers
    if (maxlength == 11 && length == 1) {
        return false;
    }
    for (int num = i; num < length; num++) {
        char c = str.charAt(num);
        if (c < '0' || c > '9') {
            return false;
        }
    }

    // verify that number value is within int range
    if (length == maxlength) {
        for (; i < length; i++) {
            if (str.charAt(i) < maxnum.charAt(i)) {
                return true;
            }
            else if (str.charAt(i) > maxnum.charAt(i)) {
                return false;
            }
        }
    }
    return true;
}

1
좋아 보이지만, 마지막 숫자는 각 숫자가 숫자인지 확인하는 루프가 i를 문자열 길이로 만들기 때문에 마지막 숫자는 0으로 재설정해야합니다. 절대로 실행되지 않습니다. 또한 매직 숫자 대신 Java 상수 Integer.MAX_VALUE 및 Integer.MIN_VALUE를 사용합니다.
팀 인챈터

@TimtheEnchanter 제안을 주셔서 감사합니다, 나는 그들을 완전히 간과했습니다. 그것들을 통합하기 위해 편집 할 때 여분의 if 문을 피하기 위해 첫 번째 for 루프에서 새로운 변수를 사용했습니다.
Wayne

1

Android API를 사용하는 경우 다음을 사용할 수 있습니다.

TextUtils.isDigitsOnly(str);

1

다른 옵션 :

private boolean isNumber(String s) {
    boolean isNumber = true;
    for (char c : s.toCharArray()) {
        isNumber = isNumber && Character.isDigit(c);
    }
    return isNumber;
}

0
is_number = true;
try {
  Integer.parseInt(mystr)
} catch (NumberFormatException  e) {
  is_number = false;
}

5
이것은 포스터가 요구하는 것과 똑같은 일을하고 있습니다.
Martin Carney

0

당신이 한 일이 작동하지만 항상 그런 식으로 확인해서는 안됩니다. 예외 예외는 "예외"상황 (경우에 따라 다름)을 위해 예약해야하며 성능 측면에서 매우 비용이 많이 듭니다.


던져 질 경우에만 비용이 많이 듭니다.
Bill the Lizard

0
Number number;
try {
    number = NumberFormat.getInstance().parse("123");
} catch (ParseException e) {
    //not a number - do recovery.
    e.printStackTrace();
}
//use number

0

이것은 양의 정수에 대해서만 작동합니다.

public static boolean isInt(String str) {
    if (str != null && str.length() != 0) {
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) return false;
        }
    }
    return true;        
}

4
stackoverflow에 오신 것을 환영합니다. 오래된 스레드를 부활시키기 전에 이전 응답과 설명을 읽으십시오. 이 방법 (및 가능한 단점)은 실제로 이미 논의되었습니다.
Leigh

0

이것은 나를 위해 작동합니다. 단순히 문자열이 기본인지 또는 숫자인지 식별하기 만하면됩니다.

private boolean isPrimitive(String value){
        boolean status=true;
        if(value.length()<1)
            return false;
        for(int i = 0;i<value.length();i++){
            char c=value.charAt(i);
            if(Character.isDigit(c) || c=='.'){

            }else{
                status=false;
                break;
            }
        }
        return status;
    }

0

모든 int 문자를 확인하려면 이중 음수를 사용하면됩니다.

if (! searchString.matches ( "[^ 0-9] + $")) ...

[^ 0-9] + $는 정수가 아닌 문자가 있는지 확인하므로 테스트가 실패하면 실패합니다. 그렇지 않다면 성공하면됩니다.


아닙니다. 당신은 이것을 분명히 테스트하지 않았습니다. 문자열 어딘가에 숫자가 아닌 문자열 어딘가에 숫자가있는 경우에만 true를 리턴합니다. 이 matches방법은 문자열의 일부만이 아니라 전체 문자열과 일치합니다.
Dawood ibn Kareem

이중 부정적인 부분을 얻지 못합니다.
Roger F. Gay

글쎄, 나는 이중 부정을 얻지 못한다. 이것은 단순히 작동하지 않습니다. 숫자와 문자가 혼합되어 있으면 if블록에 들어갑니다 . 해서는 안됩니다.
Dawood ibn Kareem

0

도움이 될 수 있습니다.

public static boolean isInteger(String self) {
    try {
        Integer.valueOf(self.trim());
        return true;
    } catch (NumberFormatException nfe) {
        return false;
    }
}

0

난 당신이 아래에 볼 수 항상 안전하게 구문 분석하기 때문에 예외로 실행 제로 위험이있다 생각 intString하고 다른 길은 없어.

그래서:

  1. 당신은 확인할 경우 문자열 일치 문자 중 적어도 하나의 캐릭터의 모든 슬롯 { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} 입니다.

    if(aString.substring(j, j+1).equals(String.valueOf(i)))
  2. 당신은 합계 당신이 슬롯 위의 문자에서 발생하는 모든 시간을.

    digits++;
  3. 그리고 마지막으로 당신은 확인 문자가 지정된 캐릭터 라인의 길이와 동등 시간은 당신이 정수가 발생했음을합니다.

    if(digits == aString.length())

그리고 실제로 우리는 :

    String aString = "1234224245";
    int digits = 0;//count how many digits you encountered
    for(int j=0;j<aString.length();j++){
        for(int i=0;i<=9;i++){
            if(aString.substring(j, j+1).equals(String.valueOf(i)))
                    digits++;
        }
    }
    if(digits == aString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }
    
    String anotherString = "1234f22a4245";
    int anotherDigits = 0;//count how many digits you encountered
    for(int j=0;j<anotherString.length();j++){
        for(int i=0;i<=9;i++){
            if(anotherString.substring(j, j+1).equals(String.valueOf(i)))
                    anotherDigits++;
        }
    }
    if(anotherDigits == anotherString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }

결과는 다음과 같습니다.

정수입니다 !!

정수가 아닙니다 !!

마찬가지로 a String가 a float인지 a double이지만 그 경우에 하나만 발생해야 하는지를 확인할 수 있습니다 . 문자열에서 (점) 및 물론 확인 digits == (aString.length()-1)

다시 말하지만 여기에서 구문 분석 예외가 발생할 위험은 없지만 숫자 ( int 데이터 유형 이라고 함)가있는 것으로 알려진 문자열을 구문 분석하려는 경우 먼저 데이터 유형에 맞는지 확인해야합니다. 그렇지 않으면 캐스팅해야합니다.

내가 도와줬으면 좋겠다

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