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

How to check if a String is numeric in Java

在分析字符串之前,您将如何检查它是否是数字?


这通常是通过一个简单的用户定义函数(即滚动您自己的"isNumeric"函数)完成的。

类似:

1
2
3
4
5
6
7
8
public static boolean isNumeric(String str) {
  try {  
    Double.parseDouble(str);  
    return true;
  } catch(NumberFormatException e){  
    return false;  
  }  
}

但是,如果您经常调用这个函数,并且您期望许多检查由于不是数字而失败,那么这个机制的性能就不会很好,因为您依赖于为每个失败抛出异常,这是一个相当昂贵的操作。

另一种方法可能是使用正则表达式检查数字的有效性:

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

不过,要小心上面的regex机制,因为如果使用非阿拉伯数字(即0到9以外的数字),它将失败。这是因为regex的"d"部分只匹配[0-9]并且实际上不具有国际数字意识。(感谢俄勒冈主持人指出这一点!)

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

1
2
3
4
5
6
public static boolean isNumeric(String str) {
  NumberFormat formatter = NumberFormat.getInstance();
  ParsePosition pos = new ParsePosition(0);
  formatter.parse(str, pos);
  return str.length() == pos.getIndex();
}


阿帕奇公地语言3.5及以上:NumberUtils.isCreatableStringUtils.isNumeric

阿帕奇公地语言3.4及以下:NumberUtils.isNumberStringUtils.isNumeric

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


如果您使用的是Android,那么您应该使用:

1
android.text.TextUtils.isDigitsOnly(CharSequence str)

文档可在此处找到

保持简单。大多数人都可以"重新编程"(同样的事情)。


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

1
2
3
4
5
6
7
8
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是字符串中的字符数)比进行regex匹配计算效率更高。

更新:如Jean-Fran所指?ois corbett在注释中,上面的代码只验证正整数,这涵盖了我的大部分用例。下面是根据系统中使用的默认区域设置正确验证十进制数的更新代码,假定十进制分隔符在字符串中只出现一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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;
}


Java 8 lambda表达式。

1
2
String someString ="123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );


谷歌的guava库提供了一个很好的帮助方法:Ints.tryParse。您可以像使用Integer.parseInt一样使用它,但如果字符串不解析为有效整数,它将返回null而不是抛出异常。请注意,它返回的是整数,而不是int,因此必须将其转换为/autobox。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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给出的答案类似,但略有不同。在它们的实现中,覆盖下没有异常处理开销。


不要使用异常来验证您的值。使用util libs代替apache numberutils:

1
NumberUtils.isNumber(myStringValue);

编辑:

请注意,如果字符串以0开头,那么numberUtils将把您的值解释为十六进制。

1
2
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false


为什么每个人都在寻求异常/正则表达式解决方案?

虽然我可以理解大多数人使用Try/Catch都很好,但是如果你想经常这样做…这可能是非常沉重的负担。

我在这里所做的是使用regex、parseNumber()方法和数组搜索方法来查看哪种方法最有效。这次,我只看整数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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;
}

我得到的速度结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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

免责声明:我不是说这些方法是100%优化的,它们只是为了演示数据。

只有当数字小于等于4个字符,并且每个字符串总是一个数字时,才会赢得异常…在这种情况下,为什么还要开支票呢?

简而言之,如果您经常使用try/catch遇到无效的数字,这是非常痛苦的,这是有意义的。我一直遵循的一个重要规则是不要对程序流使用Try/Catch。这就是为什么。

有趣的是,简单的if char<0>9非常简单,易于编写,易于记忆(并且应该使用多种语言),并且几乎赢得了所有测试场景。

唯一的缺点是,我猜测integer.parseInt()可能处理非ASCII数字,而数组搜索方法则没有。

对于那些想知道我为什么说很容易记住字符数组1的人来说,如果你知道没有负号,你可以很容易地去掉一些这样浓缩的东西:

1
2
3
4
5
6
7
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;

最后,作为最后一个说明,我对被接受的例子中的分配操作符感到好奇,因为所有的投票都是通过的。添加的分配

1
double d = Double.parseDouble(...)

这不仅是无用的,因为您甚至不使用该值,而且它浪费了处理时间并将运行时间增加了几纳秒(这导致测试增加了100-200毫秒)。我不明白为什么有人会这样做,因为这实际上是额外的工作来降低性能。

你会认为这会被优化…也许我应该检查字节码,看看编译器在做什么。这并不能解释为什么它对我来说总是比较长,不过如果它被优化了…所以我想知道发生了什么事。注意:lengthier的意思是运行测试10000000次迭代,并且多次运行该程序(10x+)总是显示它变慢。

编辑:更新了字符的测试。isDigit()。


1
2
3
4
public static boolean isNumeric(String str)
{
    return str.matches("-?\\d+(.\\d+)?");
}

Craigtp的正则表达式(如上所示)会产生一些误报。例如,"23Y4"将被算作一个数字,因为"."匹配任何字符而不是小数点。

它还将拒绝带有前导"+"的任何数字

避免这两个小问题的另一种方法是

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


您可以使用NumberFormat#parse

1
2
3
4
5
6
7
8
try
{
     NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
    // Not a number.
}


如果你用Java开发Android应用程序,你可以使用TotutuiS.ISDigiStAudio函数。


我们可以尝试用空格(")替换给定字符串中的所有数字,如果之后字符串的长度为零,那么我们可以说给定字符串只包含数字。[如果你觉得这个答案有帮助,请考虑投票决定]例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;
    }


这是我对这个问题的回答。

一个catch-all-convenience方法,可以使用任何类型的解析器来解析任何字符串:isParsable(Object parser, String str)。解析器可以是Classobject。这也将允许您使用您编写的自定义解析器,并且应该在任何情况下都能工作,例如:

1
2
3
4
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");

这是我的代码和方法描述。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import java.lang.reflect.*;

/**
 * METHOD: isParsable<p>
<p>

 *
 * This method will look through the methods of the specified <wyn>from</wyn> parameter
 * looking for a public method name starting with"parse" which has only one String
 * parameter.<p>

 *
 * The <wyn>parser</wyn> parameter can be a class or an instantiated object, eg:
 * <wyn>Integer.class</wyn> or <wyn>new Integer(1)</wyn>. If you use a
 * <wyn>Class</wyn> type then only static methods are considered.<p>

 *
 * When looping through potential methods, it first looks at the <wyn>Class</wyn> associated
 * with the <wyn>parser</wyn> 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 <wyn>parser</wyn>
 * parameter which has no matching parse methods, a NoSuchMethodException will be thrown
 * embedded within a RuntimeException.<p>
<p>

 *
 * Example:
 * <wyn>isParsable(Boolean.class,"true");
 * 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");</wyn>
 * <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 <wyn>parser</wyn> 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;
    }
}


要仅匹配只包含ASCII数字的正基数10个整数,请使用:

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


一个良好的方法,避免尝试捕捉和处理负数和科学记数法。

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

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

例外是昂贵的,但在这种情况下,regex需要更长的时间。下面的代码显示了两个函数的简单测试——一个使用异常,另一个使用regex。在我的机器上,regex版本比异常慢10倍。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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);

}

}


Regex Matching

下面是另一个升级了"craigtp"regex的示例,它与更多的验证匹配。

1
2
3
4
public static boolean isNumeric(String str)
{
    return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
  • 只允许一个负号 ,并且必须在开头。
  • 负号后必须有数字。
  • 只允许使用一个十进制符号.
  • 小数点后必须有数字。
  • Regex Test

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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

    这是我的类,用于检查字符串是否为数字。它还修复了数字字符串:

    特征:

  • 删除不必要的零["12.0000000"->"12"]
  • 删除不必要的零["12.0580000"->"12.058"]
  • 删除非数字字符["12.00SDFSDF00"->"12"]
  • 处理负字符串值["-12020000"->"-12.02"]
  • 删除多个点["-12.0.20.000"->"-12.02"]
  • 没有额外的库,只是标准的Java
  • 干得好。。。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    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;
        }

    }

    //请检查以下代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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;
    }


    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    // only int
    public static boolean isNumber(int num)
    {
        return (num >= 48 && c <= 57); // 0 - 9
    }

    // is type of number including . - e E
    public static boolean isNumber(String s)
    {
        boolean isNumber = true;
        for(int i = 0; i < s.length() && isNumber; i++)
        {
            char c = s.charAt(i);
            isNumber = isNumber & (
                (c >= '0' && c <= '9') || (c == '.') || (c == 'e') || (c == 'E') || (c == '')
            );
        }
        return isInteger;
    }

    // is type of number
    public static boolean isInteger(String s)
    {
        boolean isInteger = true;
        for(int i = 0; i < s.length() && isInteger; i++)
        {
            char c = s.charAt(i);
            isInteger = isInteger & ((c >= '0' && c <= '9'));
        }
        return isInteger;
    }

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

    您可以使用java.util.scanner对象。

    1
    2
    3
    4
    public static boolean isNumeric(String inputData) {
          Scanner sc = new Scanner(inputData);
          return sc.hasNextInt();
        }

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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;
    }

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

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

    例子

    1
    2
    3
    4
    5
    6
    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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    boolean parseInteger(String s, out int number)
    {
        try {
            number = Integer.parseInt(myString);
            return true;
        } catch(NumberFormatException e) {
            return false;
        }
    }

    用途:

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


    解析它(即使用Integer#parseInt)并简单地捕获异常。=)

    为了澄清:parseint函数检查它是否可以在任何情况下(显然)解析数字,如果您无论如何都想解析它,那么您不会因为实际执行解析而受到任何性能影响。

    如果您不想解析它(或者很少解析它),那么您当然可能希望以不同的方式进行解析。


    您可以使用ApacheCommonsLang中的numberUtils.isCreatable()。

    由于NumberUtils.isNumber将在4.0中被弃用,因此请改用NumberUtils.isCreatable()。


    如果你们用以下方法检查:

    1
    2
    3
    4
    5
    6
    public static boolean isNumeric(String str) {
        NumberFormat formatter = NumberFormat.getInstance();
        ParsePosition pos = new ParsePosition(0);
        formatter.parse(str, pos);
        return str.length() == pos.getIndex();
    }

    那么,如果输入很长的字符串,会发生什么情况,比如我调用这个方法:

    1
    System.out.println(isNumeric("94328948243242352525243242524243425452342343948923"));

    结果是"真的",而且尺寸太大!如果使用regex进行检查,也会发生同样的事情!所以我宁愿使用"解析"方法来检查,如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    public static boolean isNumeric(String str) {
        try {
            int number = Integer.parseInt(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    结果就是我所期望的!


    我已经说明了一些不使用任何API检查数字和小数的条件,

    检查固定长度1位数字

    1
    Character.isDigit(char)

    检查固定长度编号(假设长度为6)

    1
    2
    3
    String number ="132452";
    if(number.matches("([0-9]{6})"))
    System.out.println("6 digits number identified");

    检查不同长度之间的数字(假设长度为4到6)

    1
    2
    3
    4
    5
    6
    7
    8
    //  {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");

    检查不同长度的十进制数(假设长度为4到7)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    //  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");

    希望能对大家有所帮助。


    使用intstream并行检查非常长的字符串

    在Java 8中,如果给定的EDCOX1(0)的所有字符都在"0"到"9"中,则进行以下测试。注意接受空字符串:

    1
    string.chars().unordered().parallel().allMatch( i -> '0' <= i && '9' >= i )

    这是我知道的检查字符串是否为数字的最快方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public static boolean isNumber(String str){
      int i=0, len=str.length();
      boolean a=false,b=false,c=false, d=false;
      if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-')) i++;
      while( i<len && isDigit(str.charAt(i)) ){ i++; a=true; }
      if(i<len && (str.charAt(i)=='.')) i++;
      while( i<len && isDigit(str.charAt(i)) ){ i++; b=true; }
      if(i<len && (str.charAt(i)=='e' || str.charAt(i)=='E') && (a || b)){ i++; c=true; }
      if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-') && c) i++;
      while( i<len && isDigit(str.charAt(i)) ){ i++; d=true;}
      return i==len && (a||b) && (!c || (c && d));
    }
    static boolean isDigit(char c){
      return c=='0' || c=='1' || c=='2' || c=='3' || c=='4' || c=='5' || c=='6' || c=='7' || c=='8' || c=='9';
    }

    如果字符串可能包含小数,则可以使用BigDecimal

    1
    2
    3
    4
    5
    try {
        new java.math.BigInteger(testString);
    } catch(NumberFormatException e) {
        throw new RuntimeException("Not a valid number");
    }


    这里有两种可能有效的方法。(不使用例外)。注意:Java是默认值传递的,字符串的值是字符串对象数据的地址。所以,当你这样做的时候

    1
    stringNumber = stringNumber.replaceAll("","");

    您已将输入值更改为没有空格。如果需要,可以删除该行。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    private boolean isValidStringNumber(String stringNumber)
    {
        if(stringNumber.isEmpty())
        {
            return false;
        }

        stringNumber = stringNumber.replaceAll("","");

        char [] charNumber = stringNumber.toCharArray();
        for(int i =0 ; i<charNumber.length ;i++)
        {
            if(!Character.isDigit(charNumber[i]))
            {
                return false;
            }
        }
        return true;
    }

    下面是另一个方法,以防您希望允许浮动据称,此方法允许表单中的数字通过1123123123123.123我刚做的,我认为它需要进一步的测试,以确保它的工作。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    private boolean isValidStringTrueNumber(String stringNumber)
    {
        if(stringNumber.isEmpty())
        {
            return false;
        }

        stringNumber = stringNumber.replaceAll("","");
        int countOfDecimalPoint = 0;
        boolean decimalPointPassed = false;
        boolean commaFound = false;
        int countOfDigitsBeforeDecimalPoint = 0;
        int countOfDigitsAfterDecimalPoint =0 ;
        int commaCounter=0;
        int countOfDigitsBeforeFirstComma = 0;

        char [] charNumber = stringNumber.toCharArray();
        for(int i =0 ; i<charNumber.length ;i++)
        {
            if((commaCounter>3)||(commaCounter<0))
            {
                return false;
            }
            if(!Character.isDigit(charNumber[i]))//Char is not a digit.
            {
                if(charNumber[i]==',')
                {
                    if(decimalPointPassed)
                    {
                        return false;
                    }
                    commaFound = true;
                    //check that next three chars are only digits.
                    commaCounter +=3;
                }
                else if(charNumber[i]=='.')
                {
                    decimalPointPassed = true;
                    countOfDecimalPoint++;
                }
                else
                {
                    return false;
                }
            }
            else //Char is a digit.
            {
                if ((commaCounter>=0)&&(commaFound))
                {
                    if(!decimalPointPassed)
                    {
                        commaCounter--;
                    }
                }

                if(!commaFound)
                {
                    countOfDigitsBeforeFirstComma++;
                }

                if(!decimalPointPassed)
                {
                    countOfDigitsBeforeDecimalPoint++;
                }
                else
                {
                    countOfDigitsAfterDecimalPoint++;
                }
            }
        }
        if((commaFound)&&(countOfDigitsBeforeFirstComma>3))
        {
            return false;
        }
        if(countOfDecimalPoint>1)
        {
            return false;
        }

        if((decimalPointPassed)&&((countOfDigitsBeforeDecimalPoint==0)||(countOfDigitsAfterDecimalPoint==0)))
        {
            return false;
        }
        return true;
    }


    基于其他答案,我编写了自己的答案,它不使用模式或带有异常检查的解析。

    它最多检查一个负号,最多检查一个小数点。

    以下是一些例子及其结果:

    "1","-1","-1.5"和"-1.556"返回真值

    "1..5"、"1a.5"、"1.5d"、"-"和"-1"返回false

    注意:如果需要,您可以修改此参数以接受区域设置参数,并将其传递到decimalMatsymbols.getInstance()调用中,以使用特定的区域设置而不是当前区域设置。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     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;
    }

    Java 8流、lambda表达式、函数接口

    处理的所有情况(字符串为空、字符串为空等)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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();

    如果您想使用regex进行检查,您应该创建一个最终的静态模式对象,这样regex只需要编译一次。编译regex大约需要执行匹配的时间,因此采取这种预防措施可以将方法的执行时间缩短一半。

    1
    2
    3
    4
    5
    6
    final static Pattern NUMBER_PATTERN = Pattern.compile("[+-]?\\d*\\.?\\d+");

    static boolean isNumber(String input) {
        Matcher m = NUMBER_PATTERN.matcher(input);
        return m.matches();
    }

    我假设一个数字是一个只有十进制数字的字符串,可能是一个+或-符号在开始,最多一个小数点(不是在结束),没有其他字符(包括逗号,空格,其他计数系统中的数字,罗马数字,象形文字)。

    这个解决方案很简洁,速度也很快,但是这样做可以使每百万次调用节省几毫秒的时间。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    static boolean isNumber(String s) {
        final int len = s.length();
        if (len == 0) {
            return false;
        }
        int dotCount = 0;
        for (int i = 0; i < len; i++) {
            char c = s.charAt(i);
            if (c < '0' || c > '9') {
                if (i == len - 1) {//last character must be digit
                    return false;
                } else if (c == '.') {
                    if (++dotCount > 1) {
                        return false;
                    }
                } else if (i != 0 || c != '+' && c != '-') {//+ or - allowed at start
                    return false;
                }

            }
        }
        return true;
    }

    试试这个:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public  boolean isNumber(String str)
    {      
        short count = 0;
        char chc[]  = {'0','1','2','3','4','5','6','7','8','9','.','-','+'};
        for (char c : str.toCharArray())
        {  
            for (int i = 0;i < chc.length;i++)
            {
                if( c  == chc[i]){
                    count++;        
                }
             }                      
        }
        if (count != str.length() )
            return false;
        else
            return true;
    }


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


    1
    2
    3
    String text="hello 123";
    if(Pattern.matches([0-9]+))==true
    System.out.println("String"+text);

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import java.util.Scanner;

    public class TestDemo {
        public static void main(String[] args) {
            boolean flag = true;
            Scanner sc = new Scanner(System.in);
            System.out.println("Enter the String:");
            String str = sc.nextLine();

            for (int i = 0; i < str.length(); i++) {
                if(str.charAt(i) > 48 && str.charAt(i) < 58) {
                    flag = false;
                    break;
                }
            }

            if(flag == true) {
                System.out.println("String is a valid String.");
            } else {
                System.out.println("String contains number.");
            }
        }
    }