在 Java 中检查 String 是否代表整数的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/237159/
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
What's the best way to check if a String represents an integer in Java?
提问by Bill the Lizard
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 answerby CodingWithSpike) to see why I've reversed my position and accepted Jonas Klemming's answerto 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.
请参阅我的答案(基于CodingWithSpike较早的答案的基准测试)以了解为什么我改变了立场并接受了Jonas Klemming对这个问题的回答。我认为这个原始代码会被大多数人使用,因为它实现更快,更易于维护,但是当提供非整数数据时,它会慢几个数量级。
采纳答案by Jonas K
If you are not concerned with potential overflow problems this function will perform about 20-30 times faster than using Integer.parseInt()
.
如果您不关心潜在的溢出问题,此函数的执行速度将比使用Integer.parseInt()
.
public static boolean isInteger(String str) {
if (str == null) {
return false;
}
int length = str.length();
if (length == 0) {
return false;
}
int i = 0;
if (str.charAt(0) == '-') {
if (length == 1) {
return false;
}
i = 1;
}
for (; i < length; i++) {
char c = str.charAt(i);
if (c < '0' || c > '9') {
return false;
}
}
return true;
}
回答by Kristian
How about:
怎么样:
return Pattern.matches("-?\d+", input);
回答by Ovidiu Pacurar
You have it, but you should only catch NumberFormatException
.
您拥有它,但您应该只捕获NumberFormatException
.
回答by Jonny Buchanan
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):
这更短,但更短不一定更好(并且它不会捕获超出范围的整数值,如 dantel 的评论中指出的那样):
input.matches("^-?\d+$");
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 than NumberFormatException
).
就个人而言,由于实现是在辅助方法中隐藏的,并且正确性胜过长度,所以我只会使用类似于您所拥有的东西(减去捕获基Exception
类而不是NumberFormatException
)。
回答by Ricardo Acras
is_number = true;
try {
Integer.parseInt(mystr)
} catch (NumberFormatException e) {
is_number = false;
}
回答by lucas
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.
您所做的工作有效,但您可能不应该总是那样检查。抛出异常应保留用于“异常”情况(尽管可能适合您的情况),并且在性能方面成本非常高。
回答by anjanb
Integer.valueOf(string);
works for me most of the time!
大多数时候对我有用!
回答by CodingWithSpike
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.
做了一个快速的基准测试。异常实际上并不那么昂贵,除非您开始弹出多个方法并且 JVM 必须做很多工作才能使执行堆栈就位。当保持相同的方法时,他们的表现并不差。
public void RunTests()
{
String str = "1234567890";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(str);
long endTime = System.currentTimeMillis();
System.out.print("ByException: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(str);
endTime = System.currentTimeMillis();
System.out.print("ByRegex: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(str);
endTime = System.currentTimeMillis();
System.out.print("ByJonas: ");
System.out.println(endTime - startTime);
}
private boolean IsInt_ByException(String str)
{
try
{
Integer.parseInt(str);
return true;
}
catch(NumberFormatException nfe)
{
return false;
}
}
private boolean IsInt_ByRegex(String str)
{
return str.matches("^-?\d+$");
}
public boolean IsInt_ByJonas(String str)
{
if (str == null) {
return false;
}
int length = str.length();
if (length == 0) {
return false;
}
int i = 0;
if (str.charAt(0) == '-') {
if (length == 1) {
return false;
}
i = 1;
}
for (; i < length; i++) {
char c = str.charAt(i);
if (c <= '/' || c >= ':') {
return false;
}
}
return true;
}
Output:
输出:
ByException: 31
ByRegex: 453 (note: re-compiling the pattern every time)
ByJonas: 16
通过异常:31
ByRegex:453(注意:每次都重新编译模式)
乔纳斯:16
I do agree that Jonas K's solution is the most robust too. Looks like he wins :)
我同意 Jonas K 的解决方案也是最强大的。看起来他赢了:)
回答by Matthew Schinckel
You can also use the Scannerclass, and use hasNextInt()- and this allows you to test for other types, too, like floats, etc.
您还可以使用Scanner类,并使用hasNextInt()- 这也允许您测试其他类型,如浮点数等。
回答by Jon Skeet
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.
如果您的意思是“可以在 Java 中转换为 int”,那么 Jonas 的答案是一个好的开始,但并没有完全完成工作。例如,它将通过 999999999999999999999999999999。我会在方法的末尾添加来自您自己的问题的正常 try/catch 调用。
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 coulddo this bit by hand too, but it would be a lotmore complicated.
逐个字符的检查将有效地拒绝“根本不是整数”的情况,留下“它是一个整数但 Java 无法处理它”的情况由较慢的异常路由捕获。你可以做到这一点的手了,但是这将是一个很多更复杂。