4

LinkedListsとArrayListsには違いがあると思います。ArrayListsは動的配列に他なりません。したがって、ArrayListsはヒープの連続した場所に格納されていると思います(これが、O(1)getメソッドがある理由です)。問題は、ArrayListの拡張を妨げるヒープに格納された別のオブジェクトがある場合はどうなるかということです。この場合、どのように実装されますか?ArrayListの残りの部分がヒープの他の非厳密な領域に格納されている場合、getメソッドはO(1)にはなりません。

たとえば、メモリ位置10にオブジェクトがあるとします。その後、メモリ位置5にArrayListが作成されます。簡単にするために、配列リストの各要素は1バイトだけであると仮定します。これは、ArrayListが5つの要素にのみ拡張できることを意味します。

4

5 に答える 5

4

ArrayList古い配列を破棄し、新しい配列を割り当て、古い配列の値を新しい配列にコピーすることにより、使用可能なメモリによって制限される任意のサイズに拡張できます。この操作はO(n)任意の挿入にかかる可能性があり、償却コストはO(1)です。

于 2012-09-17T17:10:25.597 に答える
2

したがって、ArrayListsはヒープの連続した場所に格納されていると思います

一般的にはそうですが、JVMが何か別のことをするのを妨げるものは何もありません(JVM仕様には、配列を連続ブロックに格納する必要があるとは書かれていません)。

この関連記事も参照してください。

ArrayListの拡張を妨げる別のオブジェクトがヒープに格納されている場合はどうなりますか?

arraylistオブジェクトは、JVMにさらに多くのスペースを与えるように要求します。これは、JVMが必要に応じて割り当てます(または、割り当てられない場合はOutOfMemoryExceptionをスローします)。

于 2012-09-17T17:08:43.173 に答える
1

したがって、ArrayListsはヒープの連続した場所に格納されていると思います(これが、O(1)getメソッドがある理由です)。

他のすべての答えはここに正しいですが、私はあなたがここで行った間違った仮定に対処したいと思います:

ArrayList.get()はO(1)です。これは、配列がメモリに格納される方法ではなく、要素アクセスのコストが一定であり、ArrayList内の要素の数に比例しないためです。

ここでのO(1)は、ルックアップを1回の操作で実行できることを意味するのではなく、バッキング配列のサイズに関して複雑さが一定であることを意味します。

JVMを呼び出す場合ArrayList.get(i)でも、配列インデックスを仮想メモリアドレスに変換する必要があります。これには、OSがアドレスを実際のアドレスに変換することが含まれますが、配列に1つの要素または5000がある場合でも複雑さは同じであるため、O(1)です。 。

比較するとLinkedList.get(i)、LinkedListクラスはノードが見つかるまで各ノードをウォークスルーする必要があるため、O(1)ではありませんi。複雑さはリストの全体的なサイズとの大きさに比例しiます。

配列が連続した場所に格納されているという仮定も正しくありません。

于 2012-09-17T17:24:03.413 に答える
1

ソースコードを見ると (@GilbertoGaxiola に感謝)、最初の ArrayList はサイズ 10 の object[] を作成します。より多くのスペースが必要なため、サイズを 2 倍にし、古い配列の内容を新しい配列にコピーします。この配列が巨大になるまでに何度もいっぱいになることはありません。これにより、これは優れた実装になります。

于 2012-09-17T17:14:17.090 に答える
0

最後の説明は完全に正しいです。OS は最終的にインデックスを実際のアドレスに変換する必要があります。したがって、変換にかかる時間はすべてのインデックスで一定です。ストレージに関しては、最後の 2 番目の説明は正しいです。より多くの要素を格納する必要がある場合、サイズはちょうど 2 倍になります。

于 2014-02-08T07:07:35.390 に答える