Java LinkedList addFirst() メソッド詳解
addFirst()であるLinkedListLinkedList クラス内の重要なメソッドで、リンクリストの先頭に指定された要素を挿入するために使用されます。
メソッドの構文
public void addFirst(E e)
パラメータの説明
E e:リンクリストの先頭に追加する要素
戻り値
このメソッドには戻り値がありません(void)。
addFirst() メソッドの動作原理
addFirst()このメソッドの動作原理は次のように簡単に説明できます:
- 新しいノード(Node)オブジェクトを作成します
- 新しいノードの
nextポインタを現在の先頭ノードに向けます - 現在の先頭ノードの
prevポインタを新しいノードに向けます - リンクリストの
headポインタを新しいノードに更新します - リンクリストが以前空だった場合は、末尾ノードも新しいノードを指すようにします
- リンクリストのサイズカウントを増やします(size++)
時間計算量
addFirst() メソッドの時間計算量は O(1) です。リンクリストがどれほど大きくても、固定数の操作を実行するだけで済むためです。
使用例
いくつかの例を通して見てみましょうaddFirst()メソッドの具体的な使い方。
例 1:基本的な使い方
サンプルコード
public class AddFirstExample {
public static void main(String[] args) {
// LinkedList を作成する
LinkedList<String> fruits = new LinkedList<>();
// 初期要素を追加する
fruits.add("Banana");
fruits.add("Orange");
System.out.println("元のリンクリスト: " + fruits); // 出力: [Banana, Orange]
// addFirst() を使用して先頭に要素を追加する
fruits.addFirst("Apple");
System.out.println("追加後のリンクリスト: " + fruits); // 出力: [Apple, Banana, Orange]
}
}
例 2:連続して追加
サンプルコード
public class ContinuousAddFirst {
public static void main(String[] args) {
LinkedList<Integer> numbers = new LinkedList<>();
// addFirst() を連続して使用して要素を追加する
numbers.addFirst(3);
numbers.addFirst(2);
numbers.addFirst(1);
System.out.println(numbers); // 出力: [1, 2, 3]
// 追加した順序と最終結果の順序の関係に注意してください
}
}
例 3:add() メソッドとの違い
サンプルコード
public class AddVsAddFirst {
public static void main(String[] args) {
LinkedList<String> list1 = new LinkedList<>();
LinkedList<String> list2 = new LinkedList<>();
// add() メソッドを使用して要素を追加する
list1.add("A");
list1.add("B");
list1.add("C");
// addFirst() メソッドを使用して同じ要素を追加する
list2.addFirst("C");
list2.addFirst("B");
list2.addFirst("A");
System.out.println("add() を使用: " + list1); // 出力: [A, B, C]
System.out.println("addFirst() を使用: " + list2); // 出力: [A, B, C]
// 最終結果は同じですが、追加順序は逆になります
}
}
注意事項
addFirst() をaddFirst()使用する際は、以下の点に注意してください:
1. add() メソッドとの違い
add()メソッドはデフォルトで要素をリンクリストの末尾に追加しますaddFirst()メソッドは要素をリンクリストの先頭に追加します
2. offerFirst() メソッドとの違い
addFirst()容量制限付きのキューでは例外がスローされる可能性がありますofferFirst()容量制限付きのキューでは値を返しますfalse例外をスローする代わりに
3. null 値の処理
LinkedListnull 値の追加が許可されており、nullそのため、addFirst(null)は合法です。
4. スレッド安全性
LinkedListスレッドセーフではありません。マルチスレッド環境で使用する場合はaddFirst()外部同期が必要です。
実際の適用シナリオ
addFirst()このメソッドは以下のシナリオで特に役立ちます:
1. スタック構造の実装
スタックは「後入れ先出し」(LIFO)の構造であるため、addFirst() と removeFirst() を使用してスタックの操作をシミュレートできます。
サンプルコード
stack.addFirst("Task1"); // スタックにプッシュ
stack.addFirst("Task2"); // スタックにプッシュ
String top = stack.removeFirst(); // スタックからポップ、"Task2" を返す
2. 最近使用したリスト
最近使用(MRU)リストを実装する場合、新しくアクセスされた項目をリストの先頭に追加できます。
3. 反転操作
要素を1つずつ新しいリストに addFirst() していくことで、リストの反転を実現できます。
サンプルコード
LinkedList<Integer> reversed = new LinkedList<>();
for (Integer num : original) {
reversed.addFirst(num);
}
System.out.println(reversed); // 出力: [3, 2, 1]
パフォーマンスの考慮事項
addFirst()addFirst() メソッドはLinkedListLinkedList 内でのパフォーマンスが非常に優れています。必要な操作は次のみです:
- 新しいノードの作成
- いくつかのポインタの調整
リンクリストがどれほど大きくても、これらの操作にかかる時間は一定です(O(1) の時間計算量)。これはArrayListのadd(0, element)操作とは対照的です。後者は既存のすべての要素を移動する必要があります(O(n) の時間計算量)。
したがって、コレクションの先頭に頻繁に要素を追加する必要がある場合は、LinkedListはArrayListよりも優れた選択肢です。
よくある質問(FAQ)
Q1: addFirst() は既存の要素を上書きしますか?
いいえ、addFirst()リンクリストの先頭に新しい要素を挿入するだけで、既存の要素を上書きすることはありません。
Q2: リンクリストが空の場合、addFirst() は機能しますか?
はい、機能します。リンクリストが空の場合、addFirst()新しい要素がリンクリストの最初で唯一の要素になります。
Q3: addFirst() と push() の違いは何ですか?
にLinkedListDeque において、addFirst()とpush()は完全に同じメソッドです。push()は単なるaddFirst()の別名であり、LinkedListをスタックとして使用できるようにするためのものです。
Q4: なぜ IDE は addFirst() が Deque のメソッドであると表示するのですか?
なぜならLinkedListLinkedList は Deque を実装しており、Dequeこのインターフェースにおいて、addFirst()addFirst() は実際にはDequeインターフェースで定義されたメソッドであり、LinkedListLinkedList がその実装を提供しています。
まとめ
LinkedListのaddFirst()addFirst() メソッドは効率的な操作であり、リンクリストの先頭に要素を挿入できます。このメソッドを理解することは、LinkedList を効果的に使用するためにLinkedList非常に重要です。特に、コレクションの先頭に頻繁に要素を挿入する必要があるシナリオでは重要です。
重要なポイントのまとめ:
addFirst()リンクリストの先頭に要素を挿入する- 時間計算量は O(1)
- と
add()メソッドによって追加位置が異なる - スタック構造や最近使用したリストの実装によく使用される
- マルチスレッド環境では追加の同期が必要
適切に使用することで、addFirst()このメソッドの性能を最大限に発揮し、LinkedList特定のシナリオにおけるパフォーマンス上の優位性を引き出すことができます。