web-dev-qa-db-ja.com

javaで文字列を整数に変換する最も効率的な方法

StringをIntegerオブジェクトに変換する方法はたくさんあります。以下の中で最も効率的です。

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

私のユースケースでは、ラッパーIntegerオブジェクトを作成する必要があります...つまり、プリミティブintはありません...変換されたデータは読み取り専用に使用されます。

25

それについて考える時間を無駄にしないでください。残りのコードに適合すると思われるものを選択するだけです(他の変換では.parse __()または.valueOf()メソッドを使用しますか?一貫性を保つためにそれを使用してください)。

「最適」なものを決定しようとすると、ビジネス上の問題の解決や機能の実装から集中力が失われます。

ささいな詳細で気を抜かないでください。 :-)

余談ですが、「ユースケース」がコードにJava=オブジェクトデータタイプを指定している場合、BAはドメインから離れる必要があります。BAは「ビジネス上の問題」を定義する必要があります。 、および問題に対処する際にユーザーがアプリケーションと対話する方法。開発者は、コードを使用してその機能をアプリケーションに組み込む方法(データを処理する適切なデータ型/オブジェクトを含む)を決定します。

6
Ron Savage

効率が気になる場合は、Integerオブジェクトの作成は解析よりもはるかにコストがかかります。 Integerオブジェクトを作成する必要がある場合、それがどのように解析されるかについてはあまり気にしません。

注:Java 6u14では、コマンドラインオプション-Djava.lang.Integer.IntegerCache.high = 1024などを使用して、整数プールのサイズを増やすことができます。

注2:生データ(例:ファイルまたはネットワークからのバイトの場合、これらのバイトの文字列への変換も比較的高価です。カスタムパーサーを作成する場合は、文字列に変換して未加工のソースデータを解析するステップをバイパスすることをお勧めします。

注3:Integerを作成してコレクションに配置できる場合は、GNU Trove(trove4j)を使用してコレクションにプリミティブを格納できるようにすることで、これを回避できます。 Integerの作成もドロップします。

理想的には、最高のパフォーマンスを得るには、オブジェクトをまったく作成しないようにします。

27
Peter Lawrey

あなたの最善の策は、Integer.parseIntを使用することです。これはintを返しますが、これは整数にオートボックス化できます。数値が-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
22
brianegge

これは上記の選択肢の1つではありません。 IntegerConverterは問題ありませんが、そのインスタンスを作成する必要があります。 Commons LangのNumberUtilsを見てください。

Commons Lang NumberUtils

これにより、メソッドtoIntが提供されます。

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

これにより、障害が発生した場合のデフォルト値を指定できます。

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

これは私がこれまでに見つけた最良の解決策です。

10
Jon

ここにいる多くの人がパフォーマンスの問題に関する調査をどれほど迅速に却下しているかにいつも驚いています。ベース10のintの解析は、多くのプログラムで非常に一般的なタスクです。これを高速化すると、多くの環境で顕著なプラスの効果が得られます。

解析とintは実際にはかなり簡単なタスクなので、可変ベースを持つJDK実装で使用されるアプローチよりも直接的なアプローチを実装しようとしました。これは2倍以上の速さであり、それ以外は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 ) )

7
x4u

効率が気になる場合は、intを使用してください。これは、Integerよりmuch高速です。

それ以外の場合、Integerクラスは少なくともいくつかの明確でクリーンな方法を提供します。

Integer myInteger = new Integer(someString);
Integer anotherInteger = Integer.valueOf(someOtherString);
5
Jim Ferrans

これは、整数を解析するさまざまな方法のパフォーマンスを比較する優れた記事です

オーバーフロー/アンダーフローチェックを使用したコードを次に示します。

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
Jay Askren

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

}
}
3
Somaiah Kumbera

ParseIntはJava.lang.Integerではなくintを返すため、tatメソッドを使用する場合は、次のようにする必要があります。

new Integer (Integer.parseInt(number));

私は何度も聞いたことがあります。メモリの理由から、new Integer()の代わりにInteger.valueOf()を呼び出す方が良いと言われています(これはpmdの予定です)

JDK 1.5では、new Integer()を呼び出すとメモリが割り当てられます。 Integer.valueOf()は、よりメモリフレンドリーです。

http://pmd.sourceforge.net/rules/migrating.html

それに加えて、Integer.valueOfはキャッシングを許可します。これは、値-127から128がインスタンスをキャッシュすることが保証されているためです。 (Java 1.5以降)

0
Tom

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





これは私以外の人にとって役に立ちますか?私がやりたいことをする方法がすでにあるので、これを書くのに時間を無駄にしましたか?

0
Matt

別の方法はこのメソッドです:

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
malitha619