Наиболее эффективный способ преобразования строки в целое число в Java - PullRequest
25 голосов
/ 23 июня 2009

Существует много способов преобразования строки в объект типа Integer. Что является наиболее эффективным среди следующих:

Integer.valueOf()
Integer.parseInt()
org.apache.commons.beanutils.converters.IntegerConverter

Мой сценарий должен создать объекты-целочисленные оболочки ... что означает отсутствие примитива int ... и преобразованные данные используются только для чтения.

Ответы [ 11 ]

27 голосов
/ 23 июня 2009

Если вам важна эффективность, то создание объекта Integer намного дороже, чем его разбор. Если вам нужно создать объект Integer, я бы не слишком беспокоился о том, как он анализируется.

Примечание. Java 6u14 позволяет увеличить размер пула целых чисел с помощью параметра командной строки -Djava.lang.Integer.IntegerCache.high = 1024.

Примечание 2: Если вы читаете необработанные данные, например, байтов из файла или сети, преобразование этих байтов в строку также является относительно дорогим. Если вы собираетесь написать собственный синтаксический анализатор, я советую обойти этап разговора со строкой и проанализировать необработанные исходные данные.

Примечание 3: Если вы создаете целое число, чтобы вы могли поместить его в коллекцию, вы можете избежать этого, используя GNU Trove (trove4j), который позволяет хранить примитивы в коллекциях, что также позволяет отказаться от создания целого числа .

В идеале, для лучшей производительности вы должны избегать создания каких-либо объектов.

22 голосов
/ 23 июня 2009

Лучше всего использовать Integer.parseInt. Это вернет int , но это может быть автоматически упаковано в целое число. Это немного быстрее, чем 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
10 голосов
/ 23 июня 2009

Я знаю, что это не из ваших вариантов выше. С IntegerConverter все в порядке, но вам нужно создать его экземпляр. Посмотрите на NumberUtils в Commons Lang:

Commons Lang NumberUtils

это обеспечивает метод toInt:

static int toInt(java.lang.String str, int defaultValue) 

, которая позволяет указать значение по умолчанию в случае сбоя.

NumberUtils.toInt("1", 0)  = 1

Это лучшее решение, которое я нашел до сих пор.

7 голосов
/ 20 января 2010

Я всегда удивляюсь, как быстро многие из нас отказываются от какого-либо расследования проблем с производительностью. Разбор 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 );
    }
}

Чтобы получить объект типа Integer, используйте автобокс или явный

Interger.valueOf( intValueOf( str ) ).

6 голосов
/ 23 июня 2009

Даже не думайте об этом. Просто выберите тот, который кажется подходящим для остальной части кода (другие преобразования используют метод .parse __ () или .valueOf () - используйте это для согласованности).

Попытка решить, что является «лучшим», отвлекает ваше внимание от решения бизнес-задачи или реализации функции.

Не увязай в мелочах. : -)

В дополнение к этому, если в вашем "сценарии использования" указаны типы данных Java-объектов для вашего кода - ваш BA должен выйти из вашего домена. BA необходимо определить «бизнес-проблему» и то, как пользователь хотел бы взаимодействовать с приложением при решении проблемы. Разработчики определяют, как лучше встроить эту функцию в приложение с помощью кода, включая соответствующие типы данных / объекты для обработки данных.

5 голосов
/ 09 июня 2015

Вот хорошая статья, сравнивающая производительность различных методов анализа целых чисел

А вот код, который используется с проверками переполнения / недостаточности.

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;
} 
5 голосов
/ 23 июня 2009

Если вам важна эффективность, используйте int: она намного быстрее, чем Integer.

В противном случае класс Integer предлагает вам как минимум пару ясных, чистых способов:

Integer myInteger = new Integer(someString);
Integer anotherInteger = Integer.valueOf(someOtherString);
3 голосов
/ 01 апреля 2014

Я попытался сравнить значения 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));

}
}
0 голосов
/ 20 мая 2013

Другим способом является этот метод:

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);
    }
}  

Надеюсь, это поможет!

0 голосов
/ 29 декабря 2012

Herro - вроде как новичок в Java, так что прости мое невежество.

Я искал способ разобрать смешанную строку (буквы и цифры) в INT (вроде как в javascript). Не могу найти ничего в файлах JAVADOC, поэтому после долгих поисков я просто написал функцию, которая делает это:

// This function takes a string mixed with numbers and letters and returns an INT with
// the first occurrence of a number (INT) in said string, ignoring the rest;
// -- Basically, loop checks if char is a digit, if yes, puts digit back into new array, if no, puts a whitespace in its place
// this creates an array with only digits; By converting it to a string and then trimming whitespaces, it gets parsed into an INT


public static int mixedStringToInt (String str) {

    boolean flag = true;
    boolean isNumber = false;
    final String refNumbers = "0123456789";

    int strlen = str.length();
    char[] numberArray = new char[strlen];
    char[] stringArray = str.toCharArray();

    for (int i = 0; i < strlen;i++){
        if(refNumbers.indexOf(stringArray[i]) > 0 && flag){
            // if current char is a digit
            isNumber = true;
            while (flag){
                numberArray[i] = stringArray[i];
                if(i+1 >= strlen || refNumbers.indexOf(stringArray[i+1]) < 0) flag = false;
                i++;
            }
        } else {
            // if current char is not a digit
            numberArray[i] = ' ';
        }
    }
    if (isNumber){
        return Integer.valueOf(new String(numberArray).trim());
    } else return 0;
}





Это полезно для кого-то, кроме меня? Я потратил впустую свое время на написание этого, потому что уже есть метод, который делает то, что я хотел сделать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...