在java中将String转换为Integer的最有效方法

Ara*_*ram 25 java optimization performance

将String转换为Integer对象的方法有很多种.以下哪项是最有效的:

Integer.valueOf()
Integer.parseInt()
org.apache.commons.beanutils.converters.IntegerConverter
Run Code Online (Sandbox Code Playgroud)

我的用例需要创建包装器Integer对象...意味着没有原始int ...并且转换后的数据用于只读.

Pet*_*rey 27

如果您关心效率,那么创建Integer对象比解析它要昂贵得多.如果你必须创建一个Integer对象,我不会过分担心如何解析它.

注意:Java 6u14允许您使用命令行选项-Djava.lang.Integer.IntegerCache.high = 1024来增加整数池的大小.

注2:如果您正在从文件或网络中读取原始数据(例如字节),则将这些字节转换为字符串也相对昂贵.如果您要编写自定义解析器,我建议绕过转换为字符串并解析原始源数据的步骤.

注意3:如果要创建一个Integer以便将它放在一个集合中,可以使用GNU Trove(trove4j)来避免这种情况,它允许您在集合中存储基元,也允许您删除Integer创建.

理想情况下,为了获得最佳性能,您要避免创建任何对象.

  • +1 for -Djava.lang.Integer.IntegerCache.high Long 也有开关吗? (2认同)

bri*_*gge 22

最好的办法是使用Integer.parseInt.这将返回一个int,但是这可以自动装入Integer.这比valueOf略快,因为当您的数字介于-128和127之间时,它将使用Integer缓存而不是创建新对象.最慢的是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
Run Code Online (Sandbox Code Playgroud)

  • 实际测试它的+1!FWIW,我认为你可以从Integer.parseInt()获得更快的结果,如果你没有把结果打包....这对我的机器来说值得额外10%左右 (2认同)

Jon*_*Jon 10

我知道这不是你上面的选择.IntegerConverter没问题,但您需要创建它的实例.看看Commons Lang中的NumberUtils:

Commons Lang NumberUtils

这提供了方法toInt:

static int toInt(java.lang.String str, int defaultValue) 
Run Code Online (Sandbox Code Playgroud)

允许您在发生故障时指定默认值.

NumberUtils.toInt("1", 0)  = 1
Run Code Online (Sandbox Code Playgroud)

这是迄今为止我发现的最佳解决方案.


x4u*_*x4u 7

我总是很惊讶很多人在这里很快就解决了对性能问题的一些调查.解析基数为10的int是许多程序中非常常见的任务.加快速度可能会在许多环境中产生明显的积极影响.

由于解析和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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

要获取它的Integer对象,请使用autoboxing或explicit

Interger.valueOf( intValueOf( str ) ).

  • @kdgregory:随着今天无处不在的普遍存在的基于文本的格式,如XML,JSON和HTTP解析数字来自字符串实际上是许多非平凡程序中非常常见的任务.我宁愿说如果你的程序在这种代码中只花费很少的时间,那么在其他地方它们可能效率很低. (7认同)
  • 人们解雇它的原因是因为在占用执行时间的1/1,000,000的情况下获得50%的改进是浪费.对于任何非平凡的程序,特别是那些涉及数据库的程序,字符串整数转换应远远少于执行时间的百万分之一. (2认同)
  • 如果您希望提高程序的整体吞吐量,那么自我25年前开始工作以来,规则并未发生变化:您创建了一个真实的工作负载,使用该工作负载分析您的应用程序,并优化实际消耗大量数据的部分时间 其他任何事情都是浪费精力. (2认同)

Ron*_*age 5

甚至不要浪费时间思考它.只需选择一个似乎与其余代码相匹配的代码(其他转换是使用.parse __()还是.valueOf()方法?使用它来保持一致).

试图确定哪个是"最佳"会减少您解决业务问题或实现该功能的重点.

不要因为琐碎的细节而陷入困境.:-)

另外,如果您的"用例"是为您的代码指定java对象数据类型 - 您的BA需要退出您的域.BA需要定义"业务问题",以及用户在解决问题时如何与应用程序进行交互.开发人员确定如何最好地使用代码将该功能构建到应用程序中 - 包括处理数据的正确数据类型/对象.

  • 完全同意BA的观点,但总体上还没有回答实际问题,并假设当问题明确涉及效率时性能无关紧要. (14认同)
  • @mikera我同意.这不应该是公认的答案,或者根本没有."回答"完全是主观的,基于意见的,甚至没有尝试回答所提出的问题. (3认同)
  • 这个问题是有数十亿数字的人们尽可能快地解析的Google的最高结果,而且公认的答案在任何方面都没有用。 (2认同)

Jim*_*ans 5

如果效率是您的关心,使用int:它是比整数快.

否则,Integer类至少为您提供一些清晰,干净的方法:

Integer myInteger = new Integer(someString);
Integer anotherInteger = Integer.valueOf(someOtherString);
Run Code Online (Sandbox Code Playgroud)


Som*_*era 5

我尝试将 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 
Run Code Online (Sandbox Code Playgroud)

所以总结如下:

如果您可以通过使用 int 获得,请使用 Integer.parseInt。

如果您绝对需要一个整数,请使用 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));

}
}
Run Code Online (Sandbox Code Playgroud)


Jay*_*ren 5

这是一篇很好的文章,比较了解析整数的不同方法的性能

这是使用的代码,带溢出/下溢检查.

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;
}
Run Code Online (Sandbox Code Playgroud)

甚至更快的实现,没有溢出/下溢检查.

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;
} 
Run Code Online (Sandbox Code Playgroud)