我通常使用以下习语来检查String是否可以转换为整数。
public boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
是我的错觉,还是你觉得这有点粗俗?还有什么更好的办法吗?
看看我的回答(带有基准,基于CodingWithSpike之前的回答),看看为什么我改变了立场,接受了Jonas Klemming对这个问题的回答。我认为大多数人都会使用这个原始代码,因为它实现起来更快,也更易于维护,但是当提供非整数数据时,它就慢了几个数量级。
我从rally25rs answer复制了代码,并添加了一些非整数数据的测试。结果不可否认地支持Jonas Klemming发布的方法。当你有整数数据时,我最初发布的Exception方法的结果非常好,但当你没有整数数据时,它们是最糟糕的,而RegEx解决方案(我敢打赌很多人使用)的结果一直很糟糕。请参阅Felipe的编译正则表达式示例,该示例要快得多。
public void runTests()
{
String big_int = "1234567890";
String non_int = "1234XY7890";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(big_int);
long endTime = System.currentTimeMillis();
System.out.print("ByException - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByException - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByRegex - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByRegex - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByJonas - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByJonas - non-integer data: ");
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;
}
结果:
ByException - integer data: 47
ByException - non-integer data: 547
ByRegex - integer data: 390
ByRegex - non-integer data: 313
ByJonas - integer data: 0
ByJonas - non-integer data: 16
我不喜欢方法与regex,因为regex不能检查范围(整数。MIN_VALUE Integer.MAX_VALUE)。
如果你希望在大多数情况下使用int值,而不是int值是不常见的,那么我建议使用Integer。valueOf或Integer。parseInt与NumberFormatException捕获。这种方法的优点-你的代码有很好的可读性:
public static boolean isInt(String s) {
try {
Integer.parseInt(s);
return true;
} catch (NumberFormatException nfe) {
return false;
}
}
如果你需要检查String是否为整数,并且关心性能,那么最好的方法是使用java jdk实现的integer。parseInt,但很少修改(用return false替换throw):
该功能性能良好,保证正确的结果:
public static boolean isInt(String s) {
int radix = 10;
if (s == null) {
return false;
}
if (radix < Character.MIN_RADIX) {
return false;
}
if (radix > Character.MAX_RADIX) {
return false;
}
int result = 0;
boolean negative = false;
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
return false;
if (len == 1) // Cannot have lone "+" or "-"
return false;
i++;
}
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++), radix);
if (digit < 0) {
return false;
}
if (result < multmin) {
return false;
}
result *= radix;
if (result < limit + digit) {
return false;
}
result -= digit;
}
} else {
return false;
}
return true;
}
做了一个快速的基准测试。异常实际上并没有那么昂贵,除非您开始弹出多个方法,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;
}
输出:
ByException: 31
ByRegex: 453(注意:每次都重新编译模式)
ByJonas: 16
我也同意Jonas K的解决方案是最稳健的。看起来他赢了:)