是否有比
更好,更优雅(和/或可能更快)的方式boolean isNumber = false;
try{
Double.valueOf(myNumber);
isNumber = true;
} catch (NumberFormatException e) {
}
...
修改: 因为我不能选择两个答案我正在使用正则表达式,因为a)它优雅而且b)说“Jon Skeet解决了问题”是一个重言式,因为Jon Skeet本身就是所有问题的解决方案。
答案 0 :(得分:9)
你可以使用正则表达式,例如String.matches("^[\\d\\-\\.]+$");
(如果你没有测试负数或浮点数,你可以简化一点)。
不确定这是否会比您概述的方法更快。
编辑:鉴于所有这些争议,我决定进行一项测试并获得一些有关这些方法的速度的数据。不是那么正确,而是他们跑得多快。
您可以阅读我的结果on my blog。 (提示:Jon Skeet FTW)。
答案 1 :(得分:9)
我不相信Java中有任何内容可以更快,更可靠地完成它,假设稍后您将要使用Double.valueOf(或类似)实际解析它。
我使用Double.parseDouble而不是Double.valueOf来避免不必要地创建一个Double,和你也可以通过检查数字来更快地摆脱明显愚蠢的数字。 / E, - 和。预先。所以,像:
public boolean isDouble(String value)
{
boolean seenDot = false;
boolean seenExp = false;
boolean justSeenExp = false;
boolean seenDigit = false;
for (int i=0; i < value.length(); i++)
{
char c = value.charAt(i);
if (c >= '0' && c <= '9')
{
seenDigit = true;
continue;
}
if ((c == '-' || c=='+') && (i == 0 || justSeenExp))
{
continue;
}
if (c == '.' && !seenDot)
{
seenDot = true;
continue;
}
justSeenExp = false;
if ((c == 'e' || c == 'E') && !seenExp)
{
seenExp = true;
justSeenExp = true;
continue;
}
return false;
}
if (!seenDigit)
{
return false;
}
try
{
Double.parseDouble(value);
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
请注意,尽管尝试了几次,但仍然不包含“NaN”或十六进制值。是否希望这些传递取决于上下文。
根据我的经验,正则表达式比上面的硬编码检查慢。
答案 2 :(得分:8)
见java.text.NumberFormat(javadoc)。
NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
Number myNumber = nf.parse(myString);
int myInt = myNumber.intValue();
double myDouble = myNumber.doubleValue();
答案 3 :(得分:5)
Double javadocs中实际给出了正确的正则表达式:
为避免在无效字符串上调用此方法并抛出NumberFormatException,可以使用下面的正则表达式来筛选输入字符串:
final String Digits = "(\\p{Digit}+)";
final String HexDigits = "(\\p{XDigit}+)";
// an exponent is 'e' or 'E' followed by an optionally
// signed decimal integer.
final String Exp = "[eE][+-]?"+Digits;
final String fpRegex =
("[\\x00-\\x20]*"+ // Optional leading "whitespace"
"[+-]?(" + // Optional sign character
"NaN|" + // "NaN" string
"Infinity|" + // "Infinity" string
// A decimal floating-point string representing a finite positive
// number without a leading sign has at most five basic pieces:
// Digits . Digits ExponentPart FloatTypeSuffix
//
// Since this method allows integer-only strings as input
// in addition to strings of floating-point literals, the
// two sub-patterns below are simplifications of the grammar
// productions from the Java Language Specification, 2nd
// edition, section 3.10.2.
// Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
"((("+Digits+"(\\.)?("+Digits+"?)("+Exp+")?)|"+
// . Digits ExponentPart_opt FloatTypeSuffix_opt
"(\\.("+Digits+")("+Exp+")?)|"+
// Hexadecimal strings
"((" +
// 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "(\\.)?)|" +
// 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
"(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +
")[pP][+-]?" + Digits + "))" +
"[fFdD]?))" +
"[\\x00-\\x20]*");// Optional trailing "whitespace"
if (Pattern.matches(fpRegex, myString))
Double.valueOf(myString); // Will not throw NumberFormatException
else {
// Perform suitable alternative action
}
但这不允许本地化表示:
要解释浮点值的本地化字符串表示形式,请使用NumberFormat的子类。
答案 4 :(得分:3)
在Apache Commons中使用StringUtils.isDouble(String)
。
答案 5 :(得分:3)
利用Skeet先生:
private boolean IsValidDoubleChar(char c)
{
return "0123456789.+-eE".indexOf(c) >= 0;
}
public boolean isDouble(String value)
{
for (int i=0; i < value.length(); i++)
{
char c = value.charAt(i);
if (IsValidDoubleChar(c))
continue;
return false;
}
try
{
Double.parseDouble(value);
return true;
}
catch (NumberFormatException e)
{
return false;
}
}
答案 6 :(得分:2)
我会一如既往地使用Jakarta commons-lang!但我不知道their implementation是否快。它不依赖于Exceptions,这可能是一个很好的性能......
答案 7 :(得分:2)
这些答案中的大多数都是有些可接受的解决方案。对于您可能关心的所有情况,所有正则表达式解决方案都存在不正确的问题。
如果你真的想确保String是一个有效的数字,那么我会使用你自己的解决方案。我想,不要忘记,大多数情况下,String将是有效的号,并且不会引发异常。因此,大多数情况下,性能将与Double.valueOf()的性能相同。
我想这不是一个答案,只不过它验证了你的初始直觉。
兰迪
答案 8 :(得分:1)
根据Phill的回答,我可以建议另一个正则表达式吗?
String.matches("^-?\\d+(\\.\\d+)?$");
答案 9 :(得分:1)
我更喜欢在Strings的char []表示中使用循环并使用Character.isDigit()方法。如果需要优雅,我认为这是可读:
package tias;
public class Main {
private static final String NUMERIC = "123456789";
private static final String NOT_NUMERIC = "1L5C";
public static void main(String[] args) {
System.out.println(isStringNumeric(NUMERIC));
System.out.println(isStringNumeric(NOT_NUMERIC));
}
private static boolean isStringNumeric(String aString) {
if (aString == null || aString.length() == 0) {
return false;
}
for (char c : aString.toCharArray() ) {
if (!Character.isDigit(c)) {
return false;
}
}
return true;
}
}
答案 10 :(得分:-1)
如果你想要一些非常快的东西,并且你非常清楚你想要接受哪种格式,你可以手动构建一个状态机DFA。这本质上是正则表达式如何工作,但你可以通过这种方式避免正则表达式编译步骤,它可能比通用正则表达式编译器更快。