如何在Java中检查字符串是否为数字
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1102891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check if a String is numeric in Java
提问by Craig Angus
How would you check if a String was a number before parsing it?
在解析一个字符串之前,你如何检查它是否是一个数字?
采纳答案by palacsint
With Apache Commons Lang3.5 and above: NumberUtils.isCreatable
or StringUtils.isNumeric
.
使用Apache Commons Lang3.5 及更高版本:NumberUtils.isCreatable
或StringUtils.isNumeric
.
With Apache Commons Lang3.4 and below: NumberUtils.isNumber
or StringUtils.isNumeric
.
使用Apache Commons Lang3.4 及以下版本:NumberUtils.isNumber
或StringUtils.isNumeric
.
You can also use StringUtils.isNumericSpace
which returns true
for empty strings and ignores internal spaces in the string. Another way is to use NumberUtils.isParsable
which basically checks the number is parsable according to Java. (The linked javadocs contain detailed examples for each method.)
您还可以使用StringUtils.isNumericSpace
which 返回true
空字符串并忽略字符串中的内部空格。另一种方法是使用NumberUtils.isParsable
which 基本上检查数字是否可以根据 Java 解析。(链接的 javadoc 包含每种方法的详细示例。)
回答by gha.st
Parse it (i.e. with Integer#parseInt
) and simply catch the exception. =)
解析它(即使用Integer#parseInt
)并简单地捕获异常。=)
To clarify: The parseInt function checks if it can parse the number in any case (obviously) and if you want to parse it anyway, you are not going to take any performance hit by actually doing the parsing.
澄清一下: parseInt 函数检查它是否可以在任何情况下(显然)解析数字,并且如果您无论如何都想解析它,则实际进行解析不会对性能造成任何影响。
If you would not want to parse it (or parse it very, very rarely) you might wish to do it differently of course.
如果您不想解析它(或非常非常少地解析它),您当然可能希望以不同的方式进行。
回答by Artem Barger
You can use NumberFormat#parse
:
您可以使用NumberFormat#parse
:
try
{
NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
// Not a number.
}
回答by jqno
I think the only way to reliably tell if a string is a number, is to parse it. So I would just parse it, and if it's a number, you get the number in an int for free!
我认为可靠地判断字符串是否为数字的唯一方法是解析它。所以我会解析它,如果它是一个数字,你可以免费得到一个 int 中的数字!
回答by CraigTP
This is generally done with a simple user-defined function (i.e. Roll-your-own "isNumeric" function).
这通常是通过一个简单的用户定义函数来完成的(即滚动你自己的“isNumeric”函数)。
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!)
但是,请注意上述 RegEx 机制,因为如果您使用非阿拉伯数字(即 0 到 9 以外的数字),它将失败。这是因为 RegEx 的 "\d" 部分只会匹配 [0-9] 并且实际上并不具有国际数字意识。(感谢 OregonGhost 指出这一点!)
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:
或者甚至另一种选择是使用 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();
}
回答by OregonGhost
That's why I like the Try* approach in .NET. In addition to the traditional Parse method that's like the Java one, you also have a TryParse method. I'm not good in Java syntax (out parameters?), so please treat the following as some kind of pseudo-code. It should make the concept clear though.
这就是我喜欢 .NET 中的 Try* 方法的原因。除了像 Java 那样的传统 Parse 方法之外,您还有一个 TryParse 方法。我不擅长 Java 语法(输出参数?),因此请将以下内容视为某种伪代码。不过,它应该使概念清晰。
boolean parseInteger(String s, out int number)
{
try {
number = Integer.parseInt(myString);
return true;
} catch(NumberFormatException e) {
return false;
}
}
Usage:
用法:
int num;
if (parseInteger("23", out num)) {
// Do something with num.
}
回答by Ibrahim Arief
As @CraigTP had mentioned in his excellent answer, I also have similar performance concerns on using Exceptions to test whether the string is numerical or not. So I end up splitting the string and use java.lang.Character.isDigit()
.
正如@CraigTP 在他出色的回答中提到的那样,我对使用 Exceptions 测试字符串是否为数字也有类似的性能问题。所以我最终拆分字符串并使用java.lang.Character.isDigit()
.
public static boolean isNumeric(String str)
{
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;
}
According to the Javadoc, Character.isDigit(char)
will correctly recognizes non-Latin digits. Performance-wise, I think a simple N number of comparisons where N is the number of characters in the string would be more computationally efficient than doing a regex matching.
根据Javadoc,Character.isDigit(char)
将正确识别非拉丁数字。在性能方面,我认为简单的 N 次比较(其中 N 是字符串中的字符数)比进行正则表达式匹配在计算上更有效。
UPDATE: As pointed by Jean-Fran?ois Corbett in the comment, the above code would only validate positive integers, which covers the majority of my use case. Below is the updated code that correctly validates decimal numbers according to the default locale used in your system, with the assumption that decimal separator only occur once in the string.
更新:正如 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;
}
回答by user872985
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.
CraigTP 的正则表达式(如上所示)会产生一些误报。例如“23y4”将被视为一个数字,因为'.' 匹配任何字符而不是小数点。
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+)?");
}
回答by Jamie Bell
Here was my answer to the problem.
这是我对这个问题的回答。
A catch all convenience method which you can use to parse any String with any type of parser: isParsable(Object parser, String str)
. The parser can be a Class
or an object
. This will also allows you to use custom parsers you've written and should work for ever scenario, eg:
的catch你可以用它来解析与任何类型的分析器的任何字符串的所有方便的方法:isParsable(Object parser, String str)
。解析器可以是 aClass
或object
。这也将允许您使用您编写的自定义解析器,并且应该适用于任何场景,例如:
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");
Here's my code complete with method descriptions.
这是我的代码完整的方法描述。
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;
}
}
回答by quux00
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.
谷歌的番石榴库提供了一个很好的辅助方法来做到这一点:Ints.tryParse
。您可以像这样使用它,Integer.parseInt
但null
如果字符串未解析为有效整数,它会返回而不是抛出异常。请注意,它返回整数,而不是整数,因此您必须将其转换/自动装箱回整数。
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.
但是,截至当前版本——Guava r11——它仍然被标记为@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.
我没有对其进行基准测试。查看源代码,许多健全性检查会产生一些开销,但最终他们使用了Character.digit(string.charAt(idx))
与上面@Ibrahim 的答案相似但略有不同的答案。在它们的实现中没有隐藏的异常处理开销。
回答by Dayanand
You could use BigDecimal
if the string may contain decimals:
BigDecimal
如果字符串可能包含小数,您可以使用:
try {
new java.math.BigInteger(testString);
} catch(NumberFormatException e) {
throw new RuntimeException("Not a valid number");
}