リストから最初の要素を取り出して削除したい。わかりました。2つのオプションがあります。
最初のアプローチ:
LinkedList<String> servers = new LinkedList<String>();
....
String firstServerName = servers.removeFirst();
セカンドアプローチ
ArrayList<String> servers = new ArrayList<String>();
....
String firstServerName = servers.remove(0);
リストにはたくさんの要素があります。
これを行う最も効率的な方法は何ですか。
「最初に削除」の比較がArrayList
クラスとLinkedList
クラスの間である場合、LinkedList
が明らかに優先されます。
リンクリストから要素を削除するとO(1)
がかかりますが、配列(配列リスト)を削除するとO(n)
がかかります。
LinkedListとArrayListの違いを理解してください。 ArrayListは、Arrayを使用して実装されます。
LinkedListは要素を削除するのに一定の時間を要します。 ArrayListは、最初の要素を削除するために線形時間を要する場合があります(Javaエキスパート)ではなく、実装を確認する必要があることを確認するため)。
また、LinkedListはスペースの点でより効率的だと思います。 ArrayListは、要素が削除されるたびに配列のサイズを変更しない(そして変更してはならない)ため、必要以上のスペースを使用します。
実際には、LinkedList#removeFirst
は、二重にリンクされたリストで動作し、最初の要素の削除は基本的にリストの先頭からリンクを解除して次の要素を最初の要素に更新するだけなので、より効率的です。
private E unlinkFirst(Node<E> f) {
// assert f == first && f != null;
final E element = f.item;
final Node<E> next = f.next;
f.item = null;
f.next = null; // help GC
first = next;
if (next == null)
last = null;
else
next.prev = null;
size--;
modCount++;
return element;
}
ArrayList#remove
は、サブ配列をコピーして後続のすべての要素を左に1桁シフトする必要がある内部配列を操作しています。
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
一方、 LinkedList#get
操作では、指定されたインデックスにある要素を取得するために、リスト全体の半分を走査する必要があります-最悪の場合のシナリオ。 ArrayList#get
は配列を操作するため、指定されたインデックスの要素に直接アクセスします。
ここでの効率の目安は次のとおりです。
LinkedList
/add
を行う場合は、remove
を使用します(例:get
);ArrayList
/add
と比較して多くの検索操作を行う場合は、remove
を使用します。他の人が正しく指摘しているように、LinkedListは、非常に短いリスト以外のものから最初の要素を削除する場合、ArrayListよりも高速です。
ただし、それらの間で選択を行うには、操作の完全な組み合わせを考慮する必要があります。たとえば、ワークロードが最初の要素を削除するたびに100の要素リストへの数百万のインデックス付きアクセスを行う場合、ArrayListは全体的に改善されます。
リンクされたリストを使用すると、はるかに高速です。
LinkedList
最初のノードが消えるようにノードを参照するだけです。
ArrayList
配列リストの場合、基になる配列を適切に保つために、すべての要素を1スポット戻す必要があります。
必要なのはArrayDeque
(Java.util
で見過ごされがちな見過ごされているクラス)だと思います。そのremoveFirst
メソッドはLinkedList
の場合と同様にO(1)で実行されますが、一般にArrayList
のより良い空間と時間特性を示します。配列の循環キューとして実装されます。
LinkedList
を使用することはほとんどありません。 Javaプログラマーとして17年間に1回行い、振り返って後悔しました。
ArrayList の場合、最初の要素を削除すると複雑度O(n)になるため、代わりに最初の要素を取得して、削除する代わりに List.subList(int fromIndex、 int toIndex) :
final String firstServerName = servers.get(0);
servers = servers.subList(1, servers.size());
番目のアプローチ
これは、Java.util.Queueインターフェースによって公開されます。 LinkedListは、このインターフェースの実装です。
Queueインターフェースは、リスト(Queue)の先頭を効果的に削除するE poll()メソッドを公開しています。
パフォーマンスの点では、poll()メソッドはremoveFirst()と同等です。実際には、内部でremoveFirst()メソッドを使用しています。