문자열을 구문 분석하기 전에 숫자인지 어떻게 확인합니까?
답변
와 아파치 코 몬즈 랭 3.5 이상 : NumberUtils.isCreatable
나 StringUtils.isNumeric
.
와 아파치 코 몬즈 랭 3.4 이하 : NumberUtils.isNumber
나 StringUtils.isNumeric
.
빈 문자열에 대한 StringUtils.isNumericSpace
반환 값 true
을 사용 하고 문자열의 내부 공간을 무시할 수도 있습니다 . 또 다른 방법은 NumberUtils.isParsable
기본적으로 Java에 따라 파싱 가능한 수를 확인하는 사용 하는 것입니다. 링크 된 javadoc에는 각 메소드에 대한 자세한 예제가 포함되어 있습니다.
답변
이것은 일반적으로 간단한 사용자 정의 함수 (예 : Roll-your-own “isNumeric”함수)로 수행됩니다.
다음과 같은 것 :
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e){
return false;
}
}
그러나이 함수를 많이 호출하고 숫자가 아니기 때문에 많은 검사가 실패 할 것으로 예상하면이 메커니즘의 성능은 좋지 않습니다. 각 실패마다 예외가 발생하기 때문입니다. 상당히 비싼 작업입니다.
다른 방법은 정규식을 사용하여 숫자의 유효성을 검사하는 것입니다.
public static boolean isNumeric(String str) {
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
그러나 아랍어 이외의 숫자 (예 : 0에서 9 이외의 숫자)를 사용하면 위의 RegEx 메커니즘에주의해야합니다. 이는 RegEx의 “\ d”부분이 [0-9]에만 일치하고 효과적으로 국제적으로 숫자를 인식하지 못하기 때문입니다. (OregonGhost에게 이것을 지적 해 주셔서 감사합니다!)
또는 다른 대안은 Java의 내장 java.text.NumberFormat 객체를 사용하여 문자열을 구문 분석 한 후 구문 분석기 위치가 문자열의 끝에 있는지 확인하는 것입니다. 그렇다면 전체 문자열이 숫자라고 가정 할 수 있습니다.
public static boolean isNumeric(String str) {
NumberFormat formatter = NumberFormat.getInstance();
ParsePosition pos = new ParsePosition(0);
formatter.parse(str, pos);
return str.length() == pos.getIndex();
}
답변
당신이 안드로이드에 있다면, 당신은 사용해야합니다 :
android.text.TextUtils.isDigitsOnly(CharSequence str)
간단하게 유지하십시오 . 대부분의 사람들은 “다시 프로그래밍”할 수 있습니다 (같은 것).
답변
Java 8 람다 식.
String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );
답변
@CraigTP가 그의 탁월한 답변에서 언급했듯이 예외를 사용하여 문자열이 숫자인지 여부를 테스트하는 것과 비슷한 성능 문제가 있습니다. 그래서 문자열을 나누고을 사용 java.lang.Character.isDigit()
합니다.
public static boolean isNumeric(String str)
{
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;
}
에 따르면 Javadoc을 , Character.isDigit(char)
의지가 제대로 라틴어가 아닌 숫자를 인식합니다. 성능 측면에서, N이 문자열의 문자 수인 간단한 N 수의 비교는 정규식 일치를 수행하는 것보다 계산적으로 효율적이라고 생각합니다.
업데이트 : 의견에서 Jean-François Corbett이 지적한 것처럼 위의 코드는 양의 정수 만 유효성을 검사하므로 대부분의 유스 케이스를 포괄합니다. 다음은 시스템에서 사용되는 기본 로케일에 따라 소수를 올바르게 유효성 검증하는 업데이트 된 코드이며 소수 구분 기호는 문자열에서 한 번만 발생한다는 가정입니다.
public static boolean isStringNumeric( String str )
{
DecimalFormatSymbols currentLocaleSymbols = DecimalFormatSymbols.getInstance();
char localeMinusSign = currentLocaleSymbols.getMinusSign();
if ( !Character.isDigit( str.charAt( 0 ) ) && str.charAt( 0 ) != localeMinusSign ) return false;
boolean isDecimalSeparatorFound = false;
char localeDecimalSeparator = currentLocaleSymbols.getDecimalSeparator();
for ( char c : str.substring( 1 ).toCharArray() )
{
if ( !Character.isDigit( c ) )
{
if ( c == localeDecimalSeparator && !isDecimalSeparatorFound )
{
isDecimalSeparatorFound = true;
continue;
}
return false;
}
}
return true;
}
답변
Google의 구아바 라이브러리는 다음과 같은 유용한 도우미 방법을 제공합니다 Ints.tryParse
. 당신은 같이 사용할 수 Integer.parseInt
있지만 반환 null
이 아닌 문자열이 유효한 정수로 구문 분석하지 않는 경우 예외를 throw합니다. int가 아닌 Integer를 반환하므로 int로 다시 변환 / 오토 박스해야합니다.
예:
String s1 = "22";
String s2 = "22.2";
Integer oInt1 = Ints.tryParse(s1);
Integer oInt2 = Ints.tryParse(s2);
int i1 = -1;
if (oInt1 != null) {
i1 = oInt1.intValue();
}
int i2 = -1;
if (oInt2 != null) {
i2 = oInt2.intValue();
}
System.out.println(i1); // prints 22
System.out.println(i2); // prints -1
그러나 현재 릴리스 인 Guava r11에서는 여전히 @Beta로 표시되어 있습니다.
나는 그것을 벤치마킹하지 않았습니다. 소스 코드를 보면 많은 온 전성 검사로 인한 오버 헤드가 있지만 결국 Character.digit(string.charAt(idx))
@Ibrahim의 대답과 비슷하지만 약간 다릅니다. 구현시 커버 아래에서 예외 처리 오버 헤드가 없습니다.
답변
값을 확인하기 위해 예외를 사용하지 마십시오.
아파치 NumberUtils 대신 Util 라이브러리를 사용하십시오 :
NumberUtils.isNumber(myStringValue);
편집 :
문자열이 0으로 시작하면 NumberUtils는 값을 16 진수로 해석합니다.
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false