How to check if a String is numeric in Java

前端 未结 30 2502
盖世英雄少女心
盖世英雄少女心 2020-11-21 05:26

How would you check if a String was a number before parsing it?

相关标签:
30条回答
  • 2020-11-21 05:52
    public static boolean isNumeric(String str)
    {
        return str.matches("-?\\d+(.\\d+)?");
    }
    

    CraigTP's regular expression (shown above) produces some false positives. E.g. "23y4" will be counted as a number because '.' matches any character not the decimal point.

    Also it will reject any number with a leading '+'

    An alternative which avoids these two minor problems is

    public static boolean isNumeric(String str)
    {
        return str.matches("[+-]?\\d*(\\.\\d+)?");
    }
    
    0 讨论(0)
  • 2020-11-21 05:52

    Exceptions are expensive, but in this case the RegEx takes much longer. The code below shows a simple test of two functions -- one using exceptions and one using regex. On my machine the RegEx version is 10 times slower than the exception.

    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);
    
    }
    
    }
    
    0 讨论(0)
  • 2020-11-21 05:54

    Google's Guava library provides a nice helper method to do this: Ints.tryParse. You use it like Integer.parseInt but it returns null rather than throw an Exception if the string does not parse to a valid integer. Note that it returns Integer, not int, so you have to convert/autobox it back to int.

    Example:

    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
    

    However, as of the current release -- Guava r11 -- it is still marked @Beta.

    I haven't benchmarked it. Looking at the source code there is some overhead from a lot of sanity checking but in the end they use Character.digit(string.charAt(idx)), similar, but slightly different from, the answer from @Ibrahim above. There is no exception handling overhead under the covers in their implementation.

    0 讨论(0)
  • 2020-11-21 05:54

    Do not use Exceptions to validate your values. Use Util libs instead like apache NumberUtils:

    NumberUtils.isNumber(myStringValue);
    

    Edit:

    Please notice that, if your string starts with an 0, NumberUtils will interpret your value as hexadecimal.

    NumberUtils.isNumber("07") //true
    NumberUtils.isNumber("08") //false
    
    0 讨论(0)
  • 2020-11-21 05:56

    This is generally done with a simple user-defined function (i.e. Roll-your-own "isNumeric" function).

    Something like:

    public static boolean isNumeric(String str) { 
      try {  
        Double.parseDouble(str);  
        return true;
      } catch(NumberFormatException e){  
        return false;  
      }  
    }
    

    However, if you're calling this function a lot, and you expect many of the checks to fail due to not being a number then performance of this mechanism will not be great, since you're relying upon exceptions being thrown for each failure, which is a fairly expensive operation.

    An alternative approach may be to use a regular expression to check for validity of being a number:

    public static boolean isNumeric(String str) {
      return str.matches("-?\\d+(\\.\\d+)?");  //match a number with optional '-' and decimal.
    }
    

    Be careful with the above RegEx mechanism, though, as it will fail if you're using non-Arabic digits (i.e. numerals other than 0 through to 9). This is because the "\d" part of the RegEx will only match [0-9] and effectively isn't internationally numerically aware. (Thanks to OregonGhost for pointing this out!)

    Or even another alternative is to use Java's built-in java.text.NumberFormat object to see if, after parsing the string the parser position is at the end of the string. If it is, we can assume the entire string is numeric:

    public static boolean isNumeric(String str) {
      NumberFormat formatter = NumberFormat.getInstance();
      ParsePosition pos = new ParsePosition(0);
      formatter.parse(str, pos);
      return str.length() == pos.getIndex();
    }
    
    0 讨论(0)
  • 2020-11-21 05:56

    Based off of other answers I wrote my own and it doesn't use patterns or parsing with exception checking.

    It checks for a maximum of one minus sign and checks for a maximum of one decimal point.

    Here are some examples and their results:

    "1", "-1", "-1.5" and "-1.556" return true

    "1..5", "1A.5", "1.5D", "-" and "--1" return false

    Note: If needed you can modify this to accept a Locale parameter and pass that into the DecimalFormatSymbols.getInstance() calls to use a specific Locale instead of the current one.

     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;
    }
    
    0 讨论(0)
提交回复
热议问题