如何在Java中检查字符串是否为数字

如何在Java中检查字符串是否为数字,java,string,numeric,Java,String,Numeric,在解析字符串之前,如何检查字符串是否是数字?解析它(即使用)并捕获异常。=) 澄清一下:parseInt函数检查它是否在任何情况下都能解析数字(显然),如果您仍然想解析它,那么实际解析不会对性能造成任何影响 如果您不想解析它(或者非常、非常罕见地解析),您当然可能希望以不同的方式进行解析。您可以使用: 我认为唯一可靠地判断字符串是否是数字的方法是解析它。所以我只需要解析它,如果它是一个数字,你可以免费得到整数形式的数字 这通常是通过一个简单的用户定义函数(即滚动您自己的“isNumeric”函数

在解析字符串之前,如何检查字符串是否是数字?

解析它(即使用)并捕获异常。=)

澄清一下:parseInt函数检查它是否在任何情况下都能解析数字(显然),如果您仍然想解析它,那么实际解析不会对性能造成任何影响

如果您不想解析它(或者非常、非常罕见地解析),您当然可能希望以不同的方式进行解析。

您可以使用:


我认为唯一可靠地判断字符串是否是数字的方法是解析它。所以我只需要解析它,如果它是一个数字,你可以免费得到整数形式的数字

这通常是通过一个简单的用户定义函数(即滚动您自己的“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以外的数字),它将失败。这是因为正则表达式的“\d”部分将只与[0-9]匹配,并且实际上没有国际数字意识。(感谢主持人指出这一点!)

或者甚至另一种选择是使用Java的内置Java.text.NumberFormat对象来查看解析字符串后,解析器位置是否在字符串的末尾。如果是,我们可以假设整个字符串是数字:

public static boolean isNumeric(String str) {
  ParsePosition pos = new ParsePosition(0);
  NumberFormat.getInstance().parse(str, pos);
  return str.length() == pos.getIndex();
}

这就是为什么我喜欢.NET中的Try*方法。除了与Java类似的传统解析方法外,还有一个TryParse方法。我不擅长Java语法(out参数?),因此请将以下内容视为某种伪代码。不过,它应该让这个概念变得清晰

boolean parseInteger(String s, out int number)
{
    try {
        number = Integer.parseInt(myString);
        return true;
    } catch(NumberFormatException e) {
        return false;
    }
}
用法:

int num;
if (parseInteger("23", out num)) {
    // Do something with num.
}

正如@CraigTP在其出色的回答中所提到的,在使用异常测试字符串是否为数字时,我也有类似的性能问题。因此,我最终拆分字符串并使用
java.lang.Character.isDigit()

根据,
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;
}
CraigTP的正则表达式(如上所示)会产生一些误报。例如,“23y4”将被计为一个数字,因为“.”与小数点以外的任何字符匹配

它还将拒绝任何带前导“+”的数字

避免这两个小问题的另一个选择是

public static boolean isNumeric(String str)
{
    return str.matches("[+-]?\\d*(\\.\\d+)?");
}

这是我对这个问题的答案

一种方便的方法,可用于使用任何类型的解析器解析任何字符串:
isParsable(objectparser,stringstr)
。解析器可以是
对象
。这也将允许您使用您已经编写的自定义解析器,这些解析器将永远适用于场景,例如:

isParsable(Integer.class, "11");
isParsable(Double.class, "11.11");
Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");
这是我的代码,包括方法描述

import java.lang.reflect.*;

/**
 * METHOD: isParsable<p><p>
 * 
 * This method will look through the methods of the specified <code>from</code> parameter
 * looking for a public method name starting with "parse" which has only one String
 * parameter.<p>
 * 
 * The <code>parser</code> parameter can be a class or an instantiated object, eg:
 * <code>Integer.class</code> or <code>new Integer(1)</code>. If you use a
 * <code>Class</code> type then only static methods are considered.<p>
 * 
 * When looping through potential methods, it first looks at the <code>Class</code> associated
 * with the <code>parser</code> parameter, then looks through the methods of the parent's class
 * followed by subsequent ancestors, using the first method that matches the criteria specified
 * above.<p>
 * 
 * This method will hide any normal parse exceptions, but throws any exceptions due to
 * programmatic errors, eg: NullPointerExceptions, etc. If you specify a <code>parser</code>
 * parameter which has no matching parse methods, a NoSuchMethodException will be thrown
 * embedded within a RuntimeException.<p><p>
 * 
 * Example:<br>
 * <code>isParsable(Boolean.class, "true");<br>
 * isParsable(Integer.class, "11");<br>
 * isParsable(Double.class, "11.11");<br>
 * Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");<br>
 * isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");<br></code>
 * <p>
 * 
 * @param parser    The Class type or instantiated Object to find a parse method in.
 * @param str   The String you want to parse
 * 
 * @return true if a parse method was found and completed without exception
 * @throws java.lang.NoSuchMethodException If no such method is accessible 
 */
public static boolean isParsable(Object parser, String str) {
    Class theClass = (parser instanceof Class? (Class)parser: parser.getClass());
    boolean staticOnly = (parser == theClass), foundAtLeastOne = false;
    Method[] methods = theClass.getMethods();

    // Loop over methods
    for (int index = 0; index < methods.length; index++) {
        Method method = methods[index];

        // If method starts with parse, is public and has one String parameter.
        // If the parser parameter was a Class, then also ensure the method is static. 
        if(method.getName().startsWith("parse") &&
            (!staticOnly || Modifier.isStatic(method.getModifiers())) &&
            Modifier.isPublic(method.getModifiers()) &&
            method.getGenericParameterTypes().length == 1 &&
            method.getGenericParameterTypes()[0] == String.class)
        {
            try {
                foundAtLeastOne = true;
                method.invoke(parser, str);
                return true; // Successfully parsed without exception
            } catch (Exception exception) {
                // If invoke problem, try a different method
                /*if(!(exception instanceof IllegalArgumentException) &&
                   !(exception instanceof IllegalAccessException) &&
                   !(exception instanceof InvocationTargetException))
                        continue; // Look for other parse methods*/

                // Parse method refuses to parse, look for another different method
                continue; // Look for other parse methods
            }
        }
    }

    // No more accessible parse method could be found.
    if(foundAtLeastOne) return false;
    else throw new RuntimeException(new NoSuchMethodException());
}


/**
 * METHOD: willParse<p><p>
 * 
 * A convienence method which calls the isParseable method, but does not throw any exceptions
 * which could be thrown through programatic errors.<p>
 * 
 * Use of {@link #isParseable(Object, String) isParseable} is recommended for use so programatic
 * errors can be caught in development, unless the value of the <code>parser</code> parameter is
 * unpredictable, or normal programtic exceptions should be ignored.<p>
 * 
 * See {@link #isParseable(Object, String) isParseable} for full description of method
 * usability.<p>
 * 
 * @param parser    The Class type or instantiated Object to find a parse method in.
 * @param str   The String you want to parse
 * 
 * @return true if a parse method was found and completed without exception
 * @see #isParseable(Object, String) for full description of method usability 
 */
public static boolean willParse(Object parser, String str) {
    try {
        return isParsable(parser, str);
    } catch(Throwable exception) {
        return false;
    }
}

Google的Guava库提供了一个很好的帮助方法:
Ints.tryParse
。您可以像
Integer.parseInt
一样使用它,但如果字符串未解析为有效整数,它将返回
null
,而不是抛出异常。请注意,它返回的是整数,而不是int,因此必须将/autobox转换回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
然而,截至目前的版本——番石榴r11——它仍然标记为@Beta

我还没有对它进行基准测试。查看源代码时,许多健全性检查会带来一些开销,但最终他们使用了
Character.digit(string.charAt(idx))
,与上面@Ibrahim的答案类似,但略有不同。在它们的实现中,没有任何异常处理开销。

3.5及以上版本:或

3.4及以下:或

您还可以使用返回空字符串的
true
,并忽略字符串中的内部空格。另一种方法是使用,它基本上检查数字是否可以根据Java解析。(链接的Javadoc包含每个方法的详细示例。)

//仅限int
公共静态布尔值isNumber(int num)
{

return(num>=48&&c='0'&&c='0'&&c如果您使用的是android,那么您应该使用:

android.text.TextUtils.isDigitsOnly(CharSequence str)


保持简单。大多数情况下,每个人都可以“重新编程”(同样的事情)。

我修改了CraigTP的解决方案,接受科学记数法以及点和逗号作为十进制分隔符

^-?\d+([,\.]\d+)?([eE]-?\d+)?$
范例

var re = new RegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$");
re.test("-6546"); // true
re.test("-6546355e-4456"); // true
re.test("-6546.355e-4456"); // true, though debatable
re.test("-6546.35.5e-4456"); // false
re.test("-6546.35.5e-4456.6"); // false

如果您使用java开发Android应用程序,您可以使用function。

这是一种性能良好的方法,可以避免尝试捕捉和处理负数和科学符号

Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );

public static boolean isNumeric( String value ) 
{
    return value != null && PATTERN.matcher( value ).matches();
}

若要仅匹配仅包含ASCII数字的正十进制整数,请使用:

public static boolean isNumeric(String maybeNumeric) {
    return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}

这是该检查的一个简单示例:

public static boolean isNumericString(String input) {
    boolean result = false;

    if(input != null && input.length() > 0) {
        char[] charArray = input.toCharArray();

        for(char c : charArray) {
            if(c >= '0' && c <= '9') {
                // it is a digit
                result = true;
            } else {
                result = false;
                break;
            }
        }
    }

    return result;
}
公共静态布尔isNumericString(字符串输入){
布尔结果=假;
if(input!=null&&input.length()>0){
char[]charArray=input.toCharArray();
用于(字符c:charArray){

如果(c>='0'&&c这里是我的类,用于检查字符串是否为数字。它还修复了数字字符串:

特征:
  • 删除不必要的零[“12.0000000”->“12”]
  • 删除不必要的零[“12.0580000”->“12.058”]
  • var re = new RegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$"); re.test("-6546"); // true re.test("-6546355e-4456"); // true re.test("-6546.355e-4456"); // true, though debatable re.test("-6546.35.5e-4456"); // false re.test("-6546.35.5e-4456.6"); // false
    Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );
    
    public static boolean isNumeric( String value ) 
    {
        return value != null && PATTERN.matcher( value ).matches();
    }
    
    public static boolean isNumeric(String maybeNumeric) {
        return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
    }
    
    public static boolean isNumericString(String input) {
        boolean result = false;
    
        if(input != null && input.length() > 0) {
            char[] charArray = input.toCharArray();
    
            for(char c : charArray) {
                if(c >= '0' && c <= '9') {
                    // it is a digit
                    result = true;
                } else {
                    result = false;
                    break;
                }
            }
        }
    
        return result;
    }
    
    public class NumUtils {
        /**
         * Transforms a string to an integer. If no numerical chars returns a String "0".
         *
         * @param str
         * @return retStr
         */
        static String makeToInteger(String str) {
            String s = str;
            double d;
            d = Double.parseDouble(makeToDouble(s));
            int i = (int) (d + 0.5D);
            String retStr = String.valueOf(i);
            System.out.printf(retStr + "   ");
            return retStr;
        }
    
        /**
         * Transforms a string to an double. If no numerical chars returns a String "0".
         *
         * @param str
         * @return retStr
         */
        static String makeToDouble(String str) {
    
            Boolean dotWasFound = false;
            String orgStr = str;
            String retStr;
            int firstDotPos = 0;
            Boolean negative = false;
    
            //check if str is null
            if(str.length()==0){
                str="0";
            }
    
            //check if first sign is "-"
            if (str.charAt(0) == '-') {
                negative = true;
            }
    
            //check if str containg any number or else set the string to '0'
            if (!str.matches(".*\\d+.*")) {
                str = "0";
            }
    
            //Replace ',' with '.'  (for some european users who use the ',' as decimal separator)
            str = str.replaceAll(",", ".");
            str = str.replaceAll("[^\\d.]", "");
    
            //Removes the any second dots
            for (int i_char = 0; i_char < str.length(); i_char++) {
                if (str.charAt(i_char) == '.') {
                    dotWasFound = true;
                    firstDotPos = i_char;
                    break;
                }
            }
            if (dotWasFound) {
                String befDot = str.substring(0, firstDotPos + 1);
                String aftDot = str.substring(firstDotPos + 1, str.length());
                aftDot = aftDot.replaceAll("\\.", "");
                str = befDot + aftDot;
            }
    
            //Removes zeros from the begining
            double uglyMethod = Double.parseDouble(str);
            str = String.valueOf(uglyMethod);
    
            //Removes the .0
            str = str.replaceAll("([0-9])\\.0+([^0-9]|$)", "$1$2");
    
            retStr = str;
    
            if (negative) {
                retStr = "-"+retStr;
            }
    
            return retStr;
    
        }
    
        static boolean isNumeric(String str) {
            try {
                double d = Double.parseDouble(str);
            } catch (NumberFormatException nfe) {
                return false;
            }
            return true;
        }
    
    }
    
    public static boolean isNumericRegex(String str) {
        if (str == null)
            return false;
        return str.matches("-?\\d+");
    }
    
    public static boolean isNumericArray(String str) {
        if (str == null)
            return false;
        char[] data = str.toCharArray();
        if (data.length <= 0)
            return false;
        int index = 0;
        if (data[0] == '-' && data.length > 1)
            index = 1;
        for (; index < data.length; index++) {
            if (data[index] < '0' || data[index] > '9') // Character.isDigit() can go here too.
                return false;
        }
        return true;
    }
    
    public static boolean isNumericException(String str) {
        if (str == null)
            return false;
        try {  
            /* int i = */ Integer.parseInt(str);
        } catch (NumberFormatException nfe) {  
            return false;  
        }
        return true;
    }
    
    Done with: for (int i = 0; i < 10000000; i++)...
    
    With only valid numbers ("59815833" and "-59815833"):
        Array numeric took 395.808192 ms [39.5808192 ns each]
        Regex took 2609.262595 ms [260.9262595 ns each]
        Exception numeric took 428.050207 ms [42.8050207 ns each]
        // Negative sign
        Array numeric took 355.788273 ms [35.5788273 ns each]
        Regex took 2746.278466 ms [274.6278466 ns each]
        Exception numeric took 518.989902 ms [51.8989902 ns each]
        // Single value ("1")
        Array numeric took 317.861267 ms [31.7861267 ns each]
        Regex took 2505.313201 ms [250.5313201 ns each]
        Exception numeric took 239.956955 ms [23.9956955 ns each]
        // With Character.isDigit()
        Array numeric took 400.734616 ms [40.0734616 ns each]
        Regex took 2663.052417 ms [266.3052417 ns each]
        Exception numeric took 401.235906 ms [40.1235906 ns each]
    
    With invalid characters ("5981a5833" and "a"):
        Array numeric took 343.205793 ms [34.3205793 ns each]
        Regex took 2608.739933 ms [260.8739933 ns each]
        Exception numeric took 7317.201775 ms [731.7201775 ns each]
        // With a single character ("a")
        Array numeric took 291.695519 ms [29.1695519 ns each]
        Regex took 2287.25378 ms [228.725378 ns each]
        Exception numeric took 7095.969481 ms [709.5969481 ns each]
    
    With null:
        Array numeric took 214.663834 ms [21.4663834 ns each]
        Regex took 201.395992 ms [20.1395992 ns each]
        Exception numeric took 233.049327 ms [23.3049327 ns each]
        Exception numeric took 6603.669427 ms [660.3669427 ns each] if there is no if/null check
    
    public static boolean isNumericArray(String str) {
        if (str == null)
            return false;
        for (char c : str.toCharArray())
            if (c < '0' || c > '9')
                return false;
        return true;
    
    double d = Double.parseDouble(...)
    
    public static boolean isNumeric(String str)
    {
        return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
    }
    
    1                  --                   **VALID**
    1.                 --                   INVALID
    1..                --                   INVALID
    1.1                --                   **VALID**
    1.1.1              --                   INVALID
    
    -1                 --                   **VALID**
    --1                --                   INVALID
    -1.                --                   INVALID
    -1.1               --                   **VALID**
    -1.1.1             --                   INVALID
    
    import java.util.Date;
    
    
    public class IsNumeric {
    
    public static boolean isNumericOne(String s) {
        return s.matches("-?\\d+(\\.\\d+)?");  //match a number with optional '-' and decimal.      
    }
    
    public static boolean isNumericTwo(String s) {
        try {
            Double.parseDouble(s);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
    
    public static void main(String [] args) {
    
        String test = "12345.F";
    
        long before = new Date().getTime();     
        for(int x=0;x<1000000;++x) {
            //isNumericTwo(test);
            isNumericOne(test);
        }
        long after = new Date().getTime();
    
        System.out.println(after-before);
    
    }
    
    }
    
    public static boolean isNumeric(String inputData) {
          Scanner sc = new Scanner(inputData);
          return sc.hasNextInt();
        }
    
    NumberUtils.isNumber(myStringValue);
    
    NumberUtils.isNumber("07") //true
    NumberUtils.isNumber("08") //false
    
    String someString = "123123";
    boolean isNumeric = someString.chars().allMatch( Character::isDigit );
    
    String someString = null; // something="", something="123abc", something="123123"
    
    boolean isNumeric = Stream.of(someString)
                .filter(s -> s != null && !s.isEmpty())
                .filter(Pattern.compile("\\D").asPredicate().negate())
                .mapToLong(Long::valueOf)
                .boxed()
                .findAny()
                .isPresent();
    
    public static boolean isDigitsOnly(CharSequence str) {
        final int len = str.length();
        for (int i = 0; i < len; i++) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }
    
    Character.isDigit(char)
    
    String number = "132452";
    if(number.matches("([0-9]{6})"))
    System.out.println("6 digits number identified");
    
    //  {n,m}  n <= length <= m
    String number = "132452";
    if(number.matches("([0-9]{4,6})"))
    System.out.println("Number Identified between 4 to 6 length");
    
    String number = "132";
    if(!number.matches("([0-9]{4,6})"))
    System.out.println("Number not in length range or different format");
    
    //  It will not count the '.' (Period) in length
    String decimal = "132.45";
    if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
    System.out.println("Numbers Identified between 4 to 7");
    
    String decimal = "1.12";
    if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
    System.out.println("Numbers Identified between 4 to 7");
    
    String decimal = "1234";
    if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
    System.out.println("Numbers Identified between 4 to 7");
    
    String decimal = "-10.123";
    if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
    System.out.println("Numbers Identified between 4 to 7");
    
    String decimal = "123..4";
    if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
    System.out.println("Decimal not in range or different format");
    
    String decimal = "132";
    if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
    System.out.println("Decimal not in range or different format");
    
    String decimal = "1.1";
    if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
    System.out.println("Decimal not in range or different format");
    
    boolean isNumber(String str){
            if(str.length() == 0)
                return false; //To check if string is empty
            
            if(str.charAt(0) == '-')
                str = str.replaceFirst("-","");// for handling -ve numbers
        
            System.out.println(str);
            
            str = str.replaceFirst("\\.",""); //to check if it contains more than one decimal points
            
            if(str.length() == 0)
                return false; // to check if it is empty string after removing -ve sign and decimal point
            System.out.println(str);
            
            return str.replaceAll("[0-9]","").length() == 0;
        }
    
     public static boolean isNumeric(final String input) {
        //Check for null or blank string
        if(input == null || input.isBlank()) return false;
    
        //Retrieve the minus sign and decimal separator characters from the current Locale
        final var localeMinusSign = DecimalFormatSymbols.getInstance().getMinusSign();
        final var localeDecimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
    
        //Check if first character is a minus sign
        final var isNegative = input.charAt(0) == localeMinusSign;
        //Check if string is not just a minus sign
        if (isNegative && input.length() == 1) return false;
    
        var isDecimalSeparatorFound = false;
    
        //If the string has a minus sign ignore the first character
        final var startCharIndex = isNegative ? 1 : 0;
    
        //Check if each character is a number or a decimal separator
        //and make sure string only has a maximum of one decimal separator
        for (var i = startCharIndex; i < input.length(); i++) {
            if(!Character.isDigit(input.charAt(i))) {
                if(input.charAt(i) == localeDecimalSeparator && !isDecimalSeparatorFound) {
                    isDecimalSeparatorFound = true;
                } else return false;
            }
        }
        return true;
    }