26

次のサンプル コードを検討してください。

List<String> myList = new ArrayList<String>(7);
myList.add(5, "Hello");
myList.removeAll(Collections.singleton(null));

System.out.println(myList.size() + " objects:" );
for (String s : myList) {
    System.out.println("\t" + s);
}

myListは初期容量 7 で初期化され、次の行は文字列 "Hello" を位置 5 に追加しようとします。これにより、IndexOutOfBoundsException がスローされます。

スレッド「メイン」の例外 java.lang.IndexOutOfBoundsException: インデックス: 5、サイズ: 0

ArrayList に関して「初期容量」が何を意味するかについて、この質問を調べました。この特定のコンストラクターが 7 つの String 要素にスペースを割り当てていることを理解しています。リストに 8 つの要素を追加しようとすると、より多くのスペースを割り当てる必要があります。

私が理解していないのは、サイズ 7 の「空の」リストを作成せず、各インデックスに null 値を設定しない理由String[] myArray = new String[7]です。ArrayList が Java の動的配列の実装であることを学んだことを思い出すので、同様の動作が予想されます。を宣言したときに割り当てられた 7 つの文字列のスペースが実際にない場合、実際にはnew ArrayList<String>(7)何が起こっているのでしょうか?

4

3 に答える 3

22

私が理解していないのは、String[] myArray = new String[7] を宣言した場合と同様に、各インデックスに null 値を持つサイズ 7 の「空の」リストを作成しない理由です。

それは場合によっては役に立ちますが、役に立たない場合もあります。多くの場合、作成しようとしているリストのサイズ (または少なくとも推測) の上限がありますが、それを入力します...そして、間違ったサイズのリストを作成したくありません。 ..そのため、値を「設定」している間はインデックスを維持し、後でサイズを設定する必要があります。

ArrayList が Java の動的配列の実装であることを学んだことを思い出すので、同様の動作が予想されます。

いいえ、そうではありません。これは、サイズ変更が可能で、舞台裏で配列を使用するリストです。それを配列と考えないようにしてください。

new を宣言するときに割り当てられた 7 つの文字列のスペースが実際にない場合、実際にはArrayList<String>(7)何が起こっているのでしょうか?

7 つの文字列参照用のスペースがありますバッファーサイズ(容量) は少なくとも 7 ですが、リストの論理サイズは 0 のままです。何も追加していません。7 行の十分な長さの紙を 1 枚持っているようなものですが、まだ何も書いていません。

事前に入力されたリストが必要な場合は、リストを作成するメソッドを簡単に作成できます。

public static List<T> createPrefilledList(int size, T item) {
    ArrayList<T> list = new ArrayList<T>(size);
    for (int i = 0; i < size; i++) {
        list.add(item);
    }
    return list;
}
于 2012-08-10T19:31:36.997 に答える
5

配列の初期容量とそのサイズ(つまり、配列に含まれる要素の数) には違いがあります。範囲外のインデックスにアクセスしようとしているかどうかを判断するために使用されるのは、そのサイズです。

ArrayList.javaこのチェックを行うメソッドは次のとおりです。

 private void rangeCheckForAdd(int index) {
   if (index < 0 || index > this.size)
     throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
 }

ご覧のとおり、アレイの初期容量とは関係ありません。含まれる要素の数のみに基づいています。

于 2012-08-10T19:34:51.877 に答える
2

初期容量が行うことは 1 つだけです。それは、バッキング アレイのサイズを (要件ではなく) 提案します。論理的には、提案の有無にかかわらず許可される操作、または提案の内容に違いはありません。唯一の変更点は、最適化の提案として発生する可能性のある内部操作と発生しない可能性があるものです。

そのように、配列に既に存在する位置にのみ「追加」できます。位置 5 より前の要素はまだ存在しないため、例外がスローされます。Javadocから:

例外: IndexOutOfBoundsException - インデックスが範囲外の場合 (index < 0 || index > size())

于 2012-08-10T19:32:21.260 に答える