有许多方法可以将字符串转换为整数对象。在以下方法中,哪个是最有效的:
Integer.valueOf()
Integer.parseInt()
org.apache.commons.beanutils.converters.IntegerConverter
我的使用情况需要创建包装整数对象...也就是没有原始的int...并且转换后的数据用于只读。
有许多方法可以将字符串转换为整数对象。在以下方法中,哪个是最有效的:
Integer.valueOf()
Integer.parseInt()
org.apache.commons.beanutils.converters.IntegerConverter
我的使用情况需要创建包装整数对象...也就是没有原始的int...并且转换后的数据用于只读。
如果你关注效率,那么创建一个Integer对象要比解析它昂贵得多。如果你必须创建一个Integer对象,我不会太担心它是如何解析的。
注意:Java 6u14允许您使用命令行选项-Djava.lang.Integer.IntegerCache.high=1024(例如)来增加您的整数池的大小。
注意2:如果您正在读取原始数据(例如从文件或网络中读取字节),将这些字节转换为字符串也相对昂贵。如果您要编写自定义解析器,我建议您跳过转换为字符串的步骤,直接解析原始源数据。
注意3:如果您要创建一个Integer以便将其放入集合中,您可以使用GNU Trove(trove4j),它允许您在集合中存储基本类型,从而无需创建Integer对象。
理想情况下,为了获得最佳性能,您应该尽量避免创建任何对象。
您的最佳选择是使用Integer.parseInt。这将返回一个int,但可以自动装箱为Integer。当数字在-128到127之间时,它将使用整数缓存而不是创建新对象,因此略微快于valueOf方法。最慢的是Apache方法。
private String data = "99";
public void testParseInt() throws Exception {
long start = System.currentTimeMillis();
long count = 0;
for (int i = 0; i < 100000000; i++) {
Integer o = Integer.parseInt(data);
count += o.hashCode();
}
long diff = System.currentTimeMillis() - start;
System.out.println("parseInt completed in " + diff + "ms");
assert 9900000000L == count;
}
public void testValueOf() throws Exception {
long start = System.currentTimeMillis();
long count = 0;
for (int i = 0; i < 100000000; i++) {
Integer o = Integer.valueOf(data);
count += o.hashCode();
}
long diff = System.currentTimeMillis() - start;
System.out.println("valueOf completed in " + diff + "ms");
assert 9900000000L == count;
}
public void testIntegerConverter() throws Exception {
long start = System.currentTimeMillis();
IntegerConverter c = new IntegerConverter();
long count = 0;
for (int i = 0; i < 100000000; i++) {
Integer o = (Integer) c.convert(Integer.class, data);
count += o.hashCode();
}
long diff = System.currentTimeMillis() - start;
System.out.println("IntegerConverter completed in " + diff + "ms");
assert 9900000000L == count;
}
parseInt completed in 5906ms
valueOf completed in 7047ms
IntegerConverter completed in 7906ms
我总是惊讶于这里的许多人如此迅速地对一些性能问题的调查置之不理。在许多程序中,将int解析为10进制是一项非常常见的任务。加快此过程可以在许多环境中产生明显的积极影响。
由于解析int实际上是一项相当琐碎的任务,所以我尝试实现比JDK实现更直接的方法,该方法具有可变基数。结果它的速度超过两倍,并且应该与Integer.parseInt()完全相同。
public static int intValueOf( String str )
{
int ival = 0, idx = 0, end;
boolean sign = false;
char ch;
if( str == null || ( end = str.length() ) == 0 ||
( ( ch = str.charAt( 0 ) ) < '0' || ch > '9' )
&& ( !( sign = ch == '-' ) || ++idx == end || ( ( ch = str.charAt( idx ) ) < '0' || ch > '9' ) ) )
throw new NumberFormatException( str );
for(;; ival *= 10 )
{
ival += '0'- ch;
if( ++idx == end )
return sign ? ival : -ival;
if( ( ch = str.charAt( idx ) ) < '0' || ch > '9' )
throw new NumberFormatException( str );
}
}
要获取一个整数对象,可以使用自动装箱或显式地调用 Interger.valueOf(intValueOf(str))
方法。我知道这不在你上面提到的选项中。IntegerConverter还可以,但您需要创建它的实例。看一下Commons Lang中的NumberUtils:
它提供了方法toInt:
static int toInt(java.lang.String str, int defaultValue)
这使您能够在发生故障的情况下指定默认值。
NumberUtils.toInt("1", 0) = 1
这是我目前找到的最佳解决方案。
以下是使用带有溢出/下溢检查的代码。
public static int parseInt( final String s )
{
if ( string == null )
throw new NumberFormatException( "Null string" );
// Check for a sign.
int num = 0;
int sign = -1;
final int len = s.length( );
final char ch = s.charAt( 0 );
if ( ch == '-' )
{
if ( len == 1 )
throw new NumberFormatException( "Missing digits: " + s );
sign = 1;
}
else
{
final int d = ch - '0';
if ( d < 0 || d > 9 )
throw new NumberFormatException( "Malformed: " + s );
num = -d;
}
// Build the number.
final int max = (sign == -1) ?
-Integer.MAX_VALUE : Integer.MIN_VALUE;
final int multmax = max / 10;
int i = 1;
while ( i < len )
{
int d = s.charAt(i++) - '0';
if ( d < 0 || d > 9 )
throw new NumberFormatException( "Malformed: " + s );
if ( num < multmax )
throw new NumberFormatException( "Over/underflow: " + s );
num *= 10;
if ( num < (max+d) )
throw new NumberFormatException( "Over/underflow: " + s );
num -= d;
}
return sign * num;
}
甚至更快的实现,无需溢出/下溢检查。
public static int parseInt( final String s )
{
// Check for a sign.
int num = 0;
int sign = -1;
final int len = s.length( );
final char ch = s.charAt( 0 );
if ( ch == '-' )
sign = 1;
else
num = '0' - ch;
// Build the number.
int i = 1;
while ( i < len )
num = num*10 + '0' - s.charAt( i++ );
return sign * num;
}
String
数字数组转换为int
,因此效率非常重要。我使用了您更快的版本,但删除了符号检查以消除额外的if
,因为我没有负数。 - lenooh如果您关心效率,请使用int:它比Integer要快得多。
否则,Integer类至少提供了几种明确、清晰的方法:
Integer myInteger = new Integer(someString);
Integer anotherInteger = Integer.valueOf(someOtherString);
我尝试使用以下程序比较了valueOf、parseInt、Ints.tryParse、NumberUtils.createInteger和NumberUtils.toInt。我使用的是jdk 1.8.0。
如预期的那样,不需要创建Integer对象的方法最快。我的结果如下:
valueOf took: 77
parseInt took: 61
Ints.tryParse took: 117
numberUtils.createInteger took: 169
numberUtils.toInt took: 63
总结如下:
如果你可以使用int类型,那么使用Integer.parseInt。
如果你绝对需要一个Integer类型,那么使用Integer.valueOf。
如果你需要在解析时不处理异常的便利性,或者如果你不确定输入的格式(即它是一个不一定是数字的字符串),那么使用Ints.tryParse。
我使用的代码是:
public class HelloWorld {
public static int limit = 1000000;
public static String sint = "9999";
public static void main(String[] args) {
long start = System.currentTimeMillis();
for (int i = 0; i < limit; i++) {
Integer integer = Integer.valueOf(sint);
}
long end = System.currentTimeMillis();
System.out.println("valueOf took: " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < limit; i++) {
int integer = Integer.parseInt(sint);
}
end = System.currentTimeMillis();
System.out.println("parseInt took: " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < limit; i++) {
int integer = Ints.tryParse(sint);
}
end = System.currentTimeMillis();
System.out.println("Ints.tryParse took: " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < limit; i++) {
Integer integer = NumberUtils.createInteger(sint);
}
end = System.currentTimeMillis();
System.out.println("numberUtils.createInteger took: " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < limit; i++) {
int integer = NumberUtils.toInt(sint);
}
end = System.currentTimeMillis();
System.out.println("numberUtils.toInt took: " + (end - start));
}
}
ParseInt 返回一个 int,而不是 java.lang.Integer,因此如果您使用该方法,您需要执行以下操作
new Integer (Integer.parseInt(number));
另一种方法是这样的:
public class stringtoInteger {
private static int stringtoInteger(String x) {
String value = "";
for (int i = 0; i < x.length(); i++) {
char character = x.charAt(i);
if (Character.isDigit(character)) {
value = value + character;
}
}
return Integer.parseInt(value);
}
}
希望能帮到你!