学習のLinkedListとのArrayListの違いを探ります

LinkedListの&のArrayList

記事の内容の質問がある(理由を明記してください)議論するためにお問い合わせください
メール:[email protected]
マイクロ手紙:こんにちは-wgh0807
QQ:490 536 401

いくつかの時間前、私は突然私に質問をするなり、時間内にボスを問題のトラブルシューティングを行うには、問題を抱えているコードを見てすることが判明したESベースの検索のヒントを書くために使用される:「なぜあなたはLinkedListの挿入し、それを削除したり、効率化を検討するために使用されて使うのですか? 「
それは挿入および欠失効率と見なされているので、この質問は私の心を開始し、答えがあります。どのような上司は、ちょうど私に後で注意を伝えるか、言いませんでした。最後に、問題の調査とこれは何の関係もありません。

しかし、この問題はいつも私の心の中で推移している - 私は、LinkedListのを使用する理由?

大学最初の接触は、その後、C、そしてC ++でJava、およびPythonのです。C / C ++毎日の練習では、最も一般的に使用されるが配列され、C / C ++の配列は可能で拡張できませんので、私は新しい世界への扉を開いていたかのように自分自身ではなく、より複雑な配列で、ポインタに頻繁に書かれたリストを学習するとき。
その後、私は、Javaに連絡し、ジャワのコレクションとの接触は、システムがリストの拡大に無料で提供、新世界で自分自身を発見しました。相対ArrayListの拡大は、私は、時間をかけて、LinkedListの中でより多くのイタリアの午前LinkedListのに慣れるために、舞台裏必要があります。

そこで問題は、なぜあなたはいつもより少ない製品を使用しないLinkedListの組み立てはそれのこの新しい世界と呼ばれていますか?

以下は、2つのセットの間の差異の私のポイントを探るしようとします。

ドキュメントには、コントラストを記述する

文書に記述されているの両方が非常に似ています。リストを達成した、Cloneableを、Serializableインタフェースの実装技術が使用されているサイズ、などのヌルを含むすべての要素を、収容することができ、オプションのリスト操作のすべてを達成したことは、スレッドセーフです。

もちろん、2内の特定の違いがあります。文書に記載のArrayList:

sizeisEmptygetsetiterator、およびlistIterator操作は、一定の時間で実行されます。add動作はつまり、n個の要素を追加することO(N)時間を必要とし、償却定数時間で実行されます。他のすべての操作は、(大まかに)線形時間で実行されます。一定の係数は、の場合と比較して低いLinkedList実装。

前記基準は、サイズは、のisEmptyは、取得、設定、イテレータとArrayListの反復子の動作時間の複雑さは、(1)、ターゲットを増加させる(追加)の時間複雑度はO(n)はOであり、時間複雑さに応じて削除される添字O(N ^ 2)。

LinkedListのため、時間複雑度は、サイズを追加のisEmpty、反復子法は、O(1)が設定され、取得し、インデックス時間計算を削除する方法によれば、O(N)です。

以上算法都没有考虑常数、系数,以ArrayList的下标删除为例,应该为n^2/2

ここから私たちが見ることができる、ArrayListの(のパワーに比べて操作を追加および削除LinkedListのは、nの操作を考慮すると、インデックスが小さい場合には、LinkedListのはArrayListのよりも強いが、途中または戻ってくる削除する目標値で削除する必要が削除しますそれは)疑問がある場合。ArrayListにはLinkedListの場所の方法よりも強力な取得、設定されています。

基本的なストレージ構造

LinkedListの格納構造:

LinkedListのストレージ構造

各ノードは双方向のノードであり、ノードは、前のノードと後指すことができます。前者のノードオブジェクトシーケンスの黄色、後続ノードオブジェクトシアンの代表的な、赤は現在のノードの記憶領域、バラの変数および定数の代表を表します

メモリストレージ内のLinkedList:

図は、中央の2つのポインタがよくデータを格納することを、私は言葉について考えていない、非常に簡単に感じます。

しかし、PREVおよびNEXTは、Node <E>種類、であり、何のJavaのポインタが、それはありませんか?

彼らは、このようにメモリに長くすべきですか?

理想的には、メモリ形式に保存されています

これは、Javaの形で考慮に実際のメモリストレージを取る必要があり、スタック、ヒープ、定数プールがあります。

一般的な店舗のローカル変数をスタック、一定のストレージ・プール名は一定の意味;山は自然にこの責任を引き受けました。(以下は、記事のタイトルに基づいて問題がある場合は、ここに格納された個人の私の理解は、私に連絡することを覚えています)

視覚的にそれがあります。

ArrayListのストレージ構造:

アレイは、それが添字によって直接呼び出すことができるようにデータが格納されています。長さは、拡張のための十分な必要はありません。あなたは中間値を削除するときに整理する必要があります。

一般的な方法は、ここで基礎となる実装の2つのクラスをお勧め見る、私たちは映画が疲れて作ってみました。

実験の比較

テストコード

テストコードは、githubのを発見した修正案を歓迎しました。https://github.com/wgh0807/experiment/blob/master/src/test1906/test1.java

実験環境

プラットフォーム:MAC OSX 10.14.5

Javaのバージョン:1.8.0_131

実験計画

実験データ量は百万整数データ(1から1000000)です。3人の被験者:デフォルトパラメータのLinkedListは、百万のArrayListの初期化パラメータとパラメータなしのArrayListに。

各オブジェクトは個別に以下の機能のために必要な時間をテストします。

  1. オブジェクトに必要万回の時間を作成します。
  2. 順次時間を使用百万データが増加
  3. ランダムリードタイムは、千を消費する必要があります
  4. 時間と一千のランダム更新データ情報
  5. 時間によって千件のデータを削除する前に
  6. 時間によって最後の千件のデータを削除します。
  7. 時間を使わ千のランダムなデータを削除します。

実験結果

デフォルトパラメータのLinkedListが続く、(百万)1,000,000パラメータ、およびデフォルトパラメータのArrayListのArrayList。実験は、ミリ秒単位の時間を示しています。システム、リソース割り当て及び他の要因に影響を与えた結果は、結果が、比較のために同時に実行の結果のみを使用して、この実験揮発性であってもよいです。結果の同一のランは、上記の要因を受けることができるが、影響は限られており、このテストは無視できます。

根据实验结果我们可以看到:

  1. 创建一百万次对象而言,有/无参数的ArrayList时间消耗极大。
  2. 顺序增加而言,总体上LinkedList表现较为优异。
  3. 随机读取而言,LinkedList时间消耗较大,不明显。
  4. 随机更新而言,LinkedList时间消耗极大
  5. 删除前一千条数据,两项ArrayList时间消耗极大
  6. 删除最后一千条数据,三项结果无明显差异
  7. 随机删除而言,LinkedList时间消耗极大

结果解释

  1. 查看构造方法。发现LinkedList方法体为空;无参ArrayList构造对内部数组进行了初始化;整型参数ArrayList构造方法对传入参数进行了合法性判断,之后对数组进行初始化。由于ArrayList逻辑较为复杂,所以时间耗费最大。
  2. 查看顺序增加方法(add(E e))。对于LinkedList,add模块的代码量共14行,直接获取了最后一个元素,给其增加下一个节点。而ArrayList的add功能先进行了数组扩容检查,如果需要扩容则进行数组复制,代码量较大。这就是时间花销LinkedList<有参ArrayList< 无参ArrayList 的原因。
  3. 查看其get(int index)方法。LinkedList先判断下标是否存在,然后判断位置距离开始节点近还是结束节点近,之后使用for循环获取目标对象并获取值(item)。ArrayList中,首先判断下标是否存在,存在即以数组的形式访问,节省了很多时间。
  4. 查看set(int index)方法,这个方法的差距和3中相同,主要存在于获取目的节点。LinkedList使用了for循环,ArraysLink使用数组访问方式,ArraysLink在随机访问时(尤其是靠近中间值)效率会明显优于LinkedList。
  5. 删除前一千条数据需要查看remove(int index),在两端删除对于LinkedList影响较小;但是对于ArrayList来说,虽然查找对象较快,但是需要将后续节点向前紧缩,需要新建数组对象并使用copy方法对其赋值,造成了时间消耗极大的结果。
  6. 删除前一千条数据需要查看remove(int index),在两端删除对于LinkedList影响较小;对于ArrayList来说,删除尾部对象也不需要重新构建数组,所以没有明显差距。
  7. 随机删除需要查看remove(int index)方法,LinkedList和ArrayList差距主要还是在于查找对象。找到对象后删除的方法相对而言ArrayList简单一些,所以ArrayList速率会更快一些。

总结

时间方面

LinkedList 优势在于灵活可变,但是随机行为对其影响较大,需要执行for循环。虽然底层已经做了一次折半查找,但是还是比不上直接从数组获取。利用其灵活的特点,在增加、删除(除最后元素外的删除)操作时表现良好,但是对于获取系列操作(尤其是获取1/4和3/4区域数据)时较为缓慢。

ArrayList优势在于稳定连续,底层使用数组实现使得随机行为得到很好的支持。但是对于破坏其稳定性的行为,如增加、删除操作,对其影响较大。删除操作的影响和其删除元素的位置有关,如果是在最后,则压力较小,只需要置空即可;如果在中间或者前部,则需要使用copy方法,将剩余元素重新组建成为一个新的数组。增加操作则需要判断是否超过现有数组长度,如果超过则需要定义新的较长数组并将当前数组的值拷贝到新的数组中再执行设置值的操作。

空间方面

LinkedList结构较大,并且用的变量较多,较为占用空间。

ArrayList结构无参默认结构简单,空间较小,使用多为常量,占用空间较小

日常使用

日常更多的使用ArrayList,性价比更高。但是对于增删操作较为集中的情况中,可以选用LinkedList。同时需要注意,链表删除不一定比数组快,需要根据实际情况进行判断。

テキストなどの読み取りのために何かご質問、提案を持っているおかげで、ご相談ください
wgh0807によって書か

おすすめ

転載: www.cnblogs.com/wgh0807/p/11201739.html