6

int次のコードを使用して、Java(SE7)が最大値を超えるをどのように処理するかをテストしていました。

int index = 2147483647;//the maximum value of int
long size = 2147483648L; //More than the maximum value of int by 1
int safeCounter=0; //To prevent the infinite loop
while (index<size)
{
    System.out.println("Index now is : "+index);//show the int value
    index++; //increment the int value
    safeCounter++; //increment the number of desired loops
    if (safeCounter==3){
        break;//to break the loop after 3 turns
    }

}

そして私が得たものは:

現在のインデックス:2147483647現在のインデックス:-2147483648現在のインデックス:-2147483647

したがって、これに混乱した後(これを使用しないsafeCounterと、最大値と最小値の間で永久に移動し続け、例外はスローされません)、次のような状況をintどのように処理するのか疑問に思いました。ArrayList要素の数がの最大値を超えていますかint(ヒープスペースが問題ではないと仮定)?そして、ArrayListこれを処理できない場合、他に処理できるデータ構造はありますか?


int変数から得た動作についても説明できますか?

4

4 に答える 4

6

ArrayListにintの最大値よりも多くの要素を含めることはできますか?

実際にはありません。ArrayListは単一のJava配列に支えられており、配列の最大サイズはですInteger.MAX_VALUE

(仮に、Oracleは、ArrayListユーザーコードを壊すことなく配列の配列を使用するように実装をやり直すことができます。しかし、それらがそれを行う可能性はかなり低いです。)

ALinkedListは、メモリ内で表現できる限り多くの要素を処理できます。または、独自のリストタイプを実装することもできます。実際、メモリに格納できるよりも多くの要素を保持できるリストタイプを実装することもできます。リストが実際にジェネレータである場合は、無制限の数の要素を実装することもできます。

結果(etcetera)をsize()返すという事実は、実際には障害ではありません。intList API仕様は、この異常を扱います。


コードの動作は簡単に説明されています。Javaの整数演算にはサイレントオーバーフローがあります。整数型の最大の正の値に1を加算すると、最大の負の値に折り返されます。つまり、MAX_VALUE + 1 ==MIN_VALUE...整数型の場合。

于 2013-01-18T05:23:07.117 に答える
3

ArrayListはそれを処理できません。arraylistサイズの最大制限はInteger.MAX_VALUEです。任意の数の要素を含むことができるLinkedListを使用できます(実際にはメモリによって異なります):-)

于 2013-01-18T05:16:52.610 に答える
2

差出人ArrayList.java

     **
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer.
     */
     private transient Object[] elementData;

実装で配列を使用するため、を超えてインデックスを作成することはできませんInteger.MAX_VALUE。これが制限です。

動作については、この質問intをご覧ください。

于 2013-01-18T05:24:41.950 に答える
1

これは、Javaが符号付き整数を使用するためです。ArrayListインデックスは0から始まり、ArrayListに負のインデックスを提供する方法はありません。

この問題に対する考えられる解決策の1つは、最初に符号なし整数を符号付き整数に変換し、それをArrayListで使用することです。

次のスニペットを使用して、符号付きから符号なしに変換できます。

public static long getUnsigned(int signed) {
    if(signed > 0) return signed;
    long signedVal = (long)(Math.pow(2, 32)) + signed;
    return signedVal;
}
于 2013-01-18T05:29:17.043 に答える