在 Java 中检查字符串是否代表整数的最佳方法是什么?
我通常使用以下习惯用法来检查字符串是否可以转换为整数。
public boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
是只有我这么认为,还是这看起来有点老套? 有什么更好的办法呢?
查看我的答案(带有基准,基于 早期答案,作者:CodingWithSpike)看看为什么我改变了立场并接受了Jonas Klemming的回答 对于这个问题。 我认为大多数人都会使用这个原始代码,因为它实现速度更快,并且更易于维护,但是当提供非整数数据时,速度会慢几个数量级。
I normally use the following idiom to check if a String can be converted to an integer.
public boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
Is it just me, or does this seem a bit hackish? What's a better way?
See my answer (with benchmarks, based on the earlier answer by CodingWithSpike) to see why I've reversed my position and accepted Jonas Klemming's answer to this problem. I think this original code will be used by most people because it's quicker to implement, and more maintainable, but it's orders of magnitude slower when non-integer data is provided.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
如果您不担心潜在的溢出问题,该函数的执行速度将比使用 Integer.parseInt() 快 20-30 倍。
If you are not concerned with potential overflow problems this function will perform about 20-30 times faster than using
Integer.parseInt()
.您已经拥有它,但您应该只捕获
NumberFormatException
。You have it, but you should only catch
NumberFormatException
.做了一个快速基准测试。 异常实际上并没有那么昂贵,除非您开始弹出多个方法并且 JVM 必须做大量工作才能使执行堆栈就位。 当保持同样的方法时,他们的表现并不差。
输出:
我确实同意 Jonas K 的解决方案也是最强大的。 看起来他赢了:)
Did a quick benchmark. Exceptions aren't actually that expensivve, unless you start popping back multiple methods and the JVM has to do a lot of work to get the execution stack in place. When staying in the same method, they aren't bad performers.
Output:
I do agree that Jonas K's solution is the most robust too. Looks like he wins :)
虽然 Java 的标准库确实缺少这样的实用功能,但
我认为 Apache Commons 对于每个 Java 程序员来说都是“必须拥有”的,
可惜它还没有移植到 Java5
though Java's standard lib really misses such utility functions
I think that Apache Commons is a "must have" for every Java programmer
too bad it isn't ported to Java5 yet
由于人们可能仍然访问这里,并且在基准测试之后会对正则表达式产生偏见......所以我将提供基准测试的更新版本,以及正则表达式的编译版本。 与之前的基准测试相反,该基准测试表明 Regex 解决方案实际上具有一贯的良好性能。
从蜥蜴比尔复制并更新编译版本:
结果:
Since there's possibility that people still visit here and will be biased against Regex after the benchmarks... So i'm gonna give an updated version of the benchmark, with a compiled version of the Regex. Which opposed to the previous benchmarks, this one shows Regex solution actually has consistently good performance.
Copied from Bill the Lizard and updated with compiled version:
Results:
它部分取决于“可以转换为整数”的含义。
如果您的意思是“可以在 Java 中转换为 int”,那么 Jonas 的回答是一个好的开始,但并没有完全完成工作。 例如,它将传递 9999999999999999999999999999999。 我会在方法末尾添加您自己问题中的正常 try/catch 调用。
逐个字符的检查将有效地拒绝“根本不是整数”的情况,而让“它是一个整数,但 Java 无法处理它”的情况由较慢的异常路由捕获。 您也可以手动完成此操作,但会复杂很多。
It partly depend on what you mean by "can be converted to an integer".
If you mean "can be converted into an int in Java" then the answer from Jonas is a good start, but doesn't quite finish the job. It would pass 999999999999999999999999999999 for example. I would add the normal try/catch call from your own question at the end of the method.
The character-by-character checks will efficiently reject "not an integer at all" cases, leaving "it's an integer but Java can't handle it" cases to be caught by the slower exception route. You could do this bit by hand too, but it would be a lot more complicated.
只是关于正则表达式的一条评论。 这里提供的每个例子都是错误的! 如果您想使用正则表达式,请不要忘记编译模式需要花费大量时间。 This:
以及 this:
会导致在每个方法调用中编译模式。 要正确使用它,请遵循:
Just one comment about regexp. Every example provided here is wrong!. If you want to use regexp don't forget that compiling the pattern take a lot of time. This:
and also this:
causes compile of pattern in every method call. To used it correctly follow:
有guava版本:
如果解析字符串失败,它会返回null而不是抛出异常。
There is guava version:
It will return null instead of throwing an exception if it fails to parse string.
我从 Rally25rs 答案中复制了代码,并添加了一些针对非整数数据的测试。 无可否认,结果支持乔纳斯·克莱明提出的方法。 当你有整数数据时,我最初发布的 Exception 方法的结果非常好,但当你没有整数数据时,它们是最糟糕的,而 RegEx 解决方案的结果(我敢打赌很多人都使用) 始终很糟糕。 有关已编译的正则表达式示例,请参阅 Felipe 的回答,该示例要快得多。
结果:
I copied the code from rally25rs answer and added some tests for non-integer data. The results are undeniably in favor of the method posted by Jonas Klemming. The results for the Exception method that I originally posted are pretty good when you have integer data, but they're the worst when you don't, while the results for the RegEx solution (that I'll bet a lot of people use) were consistently bad. See Felipe's answer for a compiled regex example, which is much faster.
Results:
这更短,但更短不一定更好(并且它不会捕获超出范围的整数值,正如 danatel 的评论中指出的):
就个人而言,由于实现被隐藏在一个辅助方法和正确性胜过长度,我会选择类似您所拥有的东西(减去捕获基
Exception
类而不是NumberFormatException
)。This is shorter, but shorter isn't necessarily better (and it won't catch integer values which are out of range, as pointed out in danatel's comment):
Personally, since the implementation is squirrelled away in a helper method and correctness trumps length, I would just go with something like what you have (minus catching the base
Exception
class rather thanNumberFormatException
).您可以使用字符串类的 matches 方法。 [0-9] 表示它可以是的所有值,+ 表示它必须至少有一个字符长,* 表示它可以是零个或多个字符长。
You can use the matches method of the string class. The [0-9] represents all the values it can be, the + means it must be at least one character long, and the * means it can be zero or more characters long.
怎么样:
How about:
这是 Jonas Klemming 答案的 Java 8 变体:
测试代码:
测试代码的结果:
This is a Java 8 variation of Jonas Klemming answer:
Test code:
Results of the test code:
您只需检查 NumberFormatException:-
You just check NumberFormatException:-
如果您的字符串数组包含纯整数和字符串,下面的代码应该可以工作。 您只需查看第一个字符即可。
例如[“4”,“44”,“abc”,“77”,“债券”]
If your String array contains pure Integers and Strings, code below should work. You only have to look at first character.
e.g. ["4","44","abc","77","bond"]
您还可以使用 Scanner 类,并使用 hasNextInt() - 这也允许您测试其他类型,例如浮点数等。
You can also use the Scanner class, and use hasNextInt() - and this allows you to test for other types, too, like floats, etc.
另外一个选择:
Another option:
如果您想检查字符串是否表示适合 int 类型的整数,我对乔纳斯的答案做了一些修改,以便表示大于 Integer.MAX_VALUE 或小于 Integer.MIN_VALUE 的整数的字符串现在将返回错误的。 例如:“3147483647”将返回 false,因为 3147483647 大于 2147483647,同样,“-2147483649”也会返回 false,因为 -2147483649 小于 -2147483648。
If you want to check if the string represents an integer that fits in an int type, I did a little modification to the jonas' answer, so that strings that represent integers bigger than Integer.MAX_VALUE or smaller than Integer.MIN_VALUE, will now return false. For example: "3147483647" will return false because 3147483647 is bigger than 2147483647, and likewise, "-2147483649" will also return false because -2147483649 is smaller than -2147483648.
您可以尝试 apache utils
在此处查看 javadoc
You may try apache utils
See the javadoc here
这里有几个答案说尝试解析为整数并捕获 NumberFormatException 但你不应该这样做。
这种方式会创建异常对象并在每次调用它时生成堆栈跟踪,并且它不是整数。
Java 8 更好的方法是使用流:
several answers here saying to try parsing to an integer and catching the NumberFormatException but you should not do this.
That way would create exception object and generates a stack trace each time you called it and it was not an integer.
A better way with Java 8 would be to use a stream:
您可能还需要考虑用例:
如果大多数时候您期望数字有效,那么捕获异常只会在尝试转换无效数字时导致性能开销。 而调用某些
isInteger()
方法,然后使用Integer.parseInt()
进行转换将总是导致有效数字的性能开销 - 字符串是解析两次,一次通过检查,一次通过转换。You probably need to take the use case in account too:
If most of the time you expect numbers to be valid, then catching the exception is only causing a performance overhead when attempting to convert invalid numbers. Whereas calling some
isInteger()
method and then convert usingInteger.parseInt()
will always cause a performance overhead for valid numbers - the strings are parsed twice, once by the check and once by the conversion.这是对Jonas'代码的修改,用于检查字符串是否在要转换为整数的范围内。
This is a modification of Jonas' code that checks if the string is within range to be cast into an integer.
如果您使用 Android API,您可以使用:
If you are using the Android API you can use:
我相信遇到异常的风险为零,因为正如您在下面看到的,您始终安全地将
int
解析为String
,而不是相反。因此:
您检查字符串中的每个字符槽是否至少匹配
字符之一{"0","1","2","3","4","5","6","7","8","9"}.
您求和您在上述槽位中遇到的所有时间
字符。
最后,您检查遇到整数的次数是否为
个字符等于给定字符串的长度。
在实践中我们有:
结果是:
同样,您可以验证
String
是float
还是double
,但在这些情况下,您必须仅遇到一个 .< /strong>(点)在字符串中,当然还要检查digits == (aString.length()-1)
我希望我有帮助
I believe there's zero risk running into an exception, because as you can see below you always safely parse
int
toString
and not the other way around.So:
You check if every slot of character in your string matches at least
one of the characters {"0","1","2","3","4","5","6","7","8","9"}.
You sum all the times that you encountered in the slots the above
characters.
And finally you check if the times that you encountered integers as
characters equals with the length of the given string.
And in practice we have:
And the results are:
Similarly, you can validate if a
String
is afloat
or adouble
but in those cases you have to encounter only one . (dot) in the String and of course check ifdigits == (aString.length()-1)
I hope I helped
你所做的事情有效,但你可能不应该总是这样检查。 抛出异常应该保留用于“异常”情况(不过,也许适合您的情况),并且在性能方面成本非常高。
What you did works, but you probably shouldn't always check that way. Throwing exceptions should be reserved for "exceptional" situations (maybe that fits in your case, though), and are very costly in terms of performance.
这仅适用于正整数。
This would work only for positive integers.
这对我有用。 简单地识别字符串是原始字符串还是数字。
This works for me. Simply to identify whether a String is a primitive or a number.
要检查所有 int 字符,只需使用双重否定即可。
if (!searchString.matches("[^0-9]+$")) ...
[^0-9]+$ 检查是否有非整数字符,因此如果为真则测试失败。 只要不是那样,你就会真正获得成功。
To check for all int chars, you can simply use a double negative.
if (!searchString.matches("[^0-9]+$")) ...
[^0-9]+$ checks to see if there are any characters that are not integer, so the test fails if it's true. Just NOT that and you get true on success.
我在这里看到了很多答案,但大多数都能够确定字符串是否是数字,但他们无法检查数字是否在整数范围内......
因此我的目的是这样的:
I have seen a lot of answers here, but most of them are able to determine whether the String is numeric, but they fail checking whether the number is in Integer range...
Therefore I purpose something like this:
当解释比性能更重要时
我注意到许多讨论都集中在某些解决方案的效率上,但没有一个讨论为什么字符串不是整数。 而且,每个人似乎都认为数字“2.00”不等于“2”。 从数学和人类的角度来说,它们是相等的(尽管计算机科学说它们不相等,并且有充分的理由)。 这就是为什么上面的“Integer.parseInt”解决方案很弱(取决于您的要求)。
无论如何,为了让软件变得更智能、更人性化,我们需要创建像我们一样思考并解释某些事情失败的原因的软件。 本例中:
测试代码:
When explanations are more important than performance
I noticed many discussions centering how efficient certain solutions are, but none on why an string is not an integer. Also, everyone seemed to assume that the number "2.00" is not equal to "2". Mathematically and humanly speaking, they are equal (even though computer science says that they are not, and for good reason). This is why the "Integer.parseInt" solutions above are weak (depending on your requirements).
At any rate, to make software smarter and more human-friendly, we need to create software that thinks like we do and explains why something failed. In this case:
Test code: