在解析字符串之前,如何检查它是否是一个数字?
当前回答
如果你在android上,那么你应该使用:
android.text.TextUtils.isDigitsOnly(CharSequence str)
文档可以在这里找到
保持简单。大多数人都可以“重新编程”(同样的事情)。
其他回答
使用IntStream并行检查非常长的字符串
在Java 8中,以下测试给定字符串的所有字符是否都在'0'到'9'之间。注意空字符串是被接受的:
string.chars().unordered().parallel().allMatch( i -> '0' <= i && '9' >= i )
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(.\\d+)?");
}
CraigTP的正则表达式(如上所示)会产生一些误报。如。"23y4"将被算作一个数字,因为'。'匹配任何字符,而不是小数点。
此外,它将拒绝任何以“+”开头的数字
避免这两个小问题的替代方法是
public static boolean isNumeric(String str)
{
return str.matches("[+-]?\\d*(\\.\\d+)?");
}
Java 8流,lambda表达式,函数接口
处理的所有情况(字符串空,字符串空等)
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();
我修改了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
为什么每个人都在推动异常/正则表达式解决方案?
虽然我能理解大多数人都喜欢使用try/catch,但如果你想频繁地使用它……这可能会非常累人。
我在这里所做的是使用regex、parsennumber()方法和数组搜索方法来查看哪个是最有效的。这一次,我只研究了整数。
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
免责声明:我并没有声称这些方法是100%优化的,它们只是为了演示数据
当且仅当数字为4个字符或更少,并且每个字符串总是一个数字时,例外获胜……既然如此,为什么还要支票呢?
简而言之,如果使用try/catch频繁地遇到无效数字,那将非常痛苦,这是有意义的。我一直遵循的一个重要规则是永远不要在程序流中使用try/catch。这是一个例子。
有趣的是,简单的if char <0 || >9写起来非常简单,容易记忆(应该可以在多种语言中工作),并且赢得了几乎所有的测试场景。
唯一的缺点是,我猜Integer.parseInt()可能处理非ASCII数字,而数组搜索方法不。
对于那些想知道为什么我说很容易记住字符数组1的人来说,如果你知道没有负号,你可以很容易地得到一些像这样的浓缩:
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(...)
不仅没有用,因为您甚至没有使用该值,而且它浪费了处理时间,并使运行时增加了几纳秒(这导致测试中增加了100-200毫秒)。我不明白为什么有人会这么做,因为这实际上是降低性能的额外工作。
你可能会认为这会被优化掉……虽然也许我应该检查字节码,看看编译器在做什么。这并不能解释为什么它对我来说总是更长,尽管它以某种方式被优化了……所以我想知道发生了什么。注意:这里所说的更长,我的意思是运行测试10000000次迭代,并且运行该程序多次(10x+)总是显示它更慢。
编辑:更新了Character.isDigit()的测试
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- Printf与std::字符串?
- 在Jar文件中运行类
- 带参数的可运行?
- 不区分大小写的“in”
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- 如何在PHP中截断字符串最接近于一定数量的字符?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作