1. 収集
(日々の勉強メモです。気に入らない場合はコメントしないでください。修正や議論は大歓迎です!)
コレクションインターフェースとは何ですか?
Java には大きなコレクション クラスがあり、コレクションはコレクション クラス内の 1 列のコレクションです。これは、すべての単一列コレクションの親インターフェイスです。Collection のサブインターフェイスには、List インターフェイスと Set インターフェイスが含まれます。これは、すべての単一列コレクション クラスがこのインターフェイスを継承することを意味します。これは、要素の追加、削除、クエリ、走査など、コレクションに共通するいくつかの基本的なメソッドを定義します。
コレクションサブインターフェースの特徴:
1. 類似点:
- これらはすべて Collection のサブインターフェースであるため、すべて Collection インターフェースを継承し、Collection インターフェースのすべてのメソッドを定義します。
- これらはすべて非同期であり、マルチスレッド環境では実行される操作はアトミックではないため、並行クラスとして設計されています。
2. 相違点:
- リストインターフェイス:
- 要素は order で格納され、List 要素の格納および取得の順序は一貫しています。つまり、追加された順序で格納および取得されます。
- 要素は繰り返し可能であり、繰り返し要素を含めることができます。
List
繰り返し要素は保存できます。 - インデックス付きの要素: List インターフェイスは、
get(int index)
指定された位置にある要素の取得、add(int index, E element)
指定された位置に要素を追加するなど、いくつかのインデックス付きメソッドを定義します。
- インターフェースを設定します:
- 要素は順序付けされていない方法で格納され、
Set
要素が格納および追加される順序は関係ありません。つまり、要素が格納および取得される順序は保証できません。 - 要素を繰り返すことはできません:
Set
重複した要素を保存することはできません。同じ要素は 1 回だけ保存されます。 - null 要素を保存できる:
Set
null 要素は保存できますが、1 回だけです。
- 要素は順序付けされていない方法で格納され、
親クラスとしてのコレクションには次のメソッドがあります。
Collection<String> c = new ArrayList<>();
//向集合中添加元素,如果添加成功返回true,如果集合因为添加元素而改变,其他集合也应该改变。
c.add(E e);
//从集合中删除元素,如果删除成功返回true,如果集合因为删除元素而改变,其他集合也应该改变。
c.remove(Object o);
// 检查集合中是否包含指定元素,如果包含返回true。
c.contains(Object o);
// 返回集合中元素的数量。
c.size();
//检查集合是否为空,如果为空返回true。
c.isEmpty();
//返回一个迭代器,用于遍历集合中的元素。
Iterator<String> it = c.iterator();
while (it.hasNext()) {
//判断集合中还有没有没有被遍历 的元素
String str = it.next();//获取下一个没有被遍历的元素
}
//返回一个包含集合中所有元素的数组。
c.toArray();
//移除集合中的所有元素,使集合为空。
c.clear();
コレクションには、親インターフェイスとして次の実装クラスがあります。
- ArrayList:配列の実装に基づいて、要素に高速かつランダムにアクセスできますが、要素を挿入または削除する場合、挿入または削除位置の要素全体を前後に移動する必要があるため、効率は低くなります。
- LinkedList:リンク リストの実装に基づいて、リストの両端の要素をすばやく挿入または削除できますが、要素にランダムにアクセスすると効率が低下します。
- HashSet:ハッシュ テーブルの実装に基づいて、要素をすばやく見つけることができますが、繰り返される要素を処理する場合は効率が低くなります。
- TreeSet:赤黒ツリーの実装に基づいて、要素を順番に保つことができますが、要素の挿入と削除の効率は低くなります。
- LinkedHashSet:ハッシュ テーブルとリンク リストの実装に基づいて、要素をすばやく見つけて順序を維持できますが、繰り返される要素を処理する場合は効率が低くなります。
さらに、Vector や Stack などの実装クラスもありますが、これらは廃止または非推奨としてマークされています。
----分割线----
2. リスト
実装クラス: ArrayList
ArrayList
Java コレクション フレームワークの実装クラスであり、動的配列に基づいて実装され、あらゆる種類のデータを格納でき、自動的に展開できます。
機能の概要:
- 動的に容量を拡張可能:
ArrayList
必要に応じて動的に容量を増やすことができ、要素数が現在の容量を超えると、より大きな内部配列が自動的に割り当てられ、元の要素が新しい配列にコピーされます。 - 高速ランダム アクセスのサポート: 動的配列の実装に基づいているため、
ArrayList
高速ランダム アクセスがサポートされ、時間計算量 O(1) でインデックスを介して要素に直接アクセスできます。 - バッチ操作のサポート:複数の要素を一度に追加する
ArrayList
一連の方法を提供し、操作の効率を向上させます。add()
- 非スレッドセーフ:
ArrayList
スレッドセーフではないため、複数のスレッドが同時に変更するとArrayList
、データの不整合が発生する可能性があります。
ArrayList の一般的な使用法:
// 使用多态创建ArrayList对象,其父类为List,子类为ArrayList。
List<String> list = new ArrayList<>();
// 添加元素
list.add(1);
list.add(1, 2); // 在指定位置插入元素
// 获取元素
String apple = list.get(0); // 获取第一个元素
// 删除元素
list.remove(0); // 删除第一个元素
//替换指定位置的元素
list.set(0, 3);
//查询指定元素的索引
int index = list.indexOf(2);
//判断列表是否为空
boolean isEmpty = list.isEmpty();
//获取列表元素数量
int size = list.size();
//将列表转换为数组
Integer[] toArray = list.toArray(new Integer[0]);
// 查询元素是否存在
boolean containsApple = list.contains(1);
// 清空列表
list.clear();
実装クラス: LinkedList
LinkedList
Java Collections Framework の実装クラスであり、要素への直接アクセスを可能にします。これは二重にリンクされたリストであり、リストの先頭と末尾での迅速な挿入および削除操作が可能です。
機能の概要:
- 動的配列:
LinkedList
動的配列は内部で使用されるため、要素の追加、削除、クエリ操作を実行するときに静的配列よりも高速です。 - 双方向の挿入・削除:先頭と末尾から挿入・削除が可能であり、
LinkedList
二重連結リストであるため先頭・末尾での効率的な挿入・削除操作がサポートされます。 - スレッドセーフではありません:
LinkedList
スレッドセーフではありません。複数のスレッドが同時に変更すると、データの不整合が発生する可能性があります。
LinkedList の一般的な用途:
// 使用多态创建LinkedList对象,其父类为List,子类为LinkedList。
List<String> list = new LinkedList<>();
// 在列表的末尾添加指定的元素。
add(E element);
//在指定位置插入指定的元素。
add(int index, E element);
//移除列表中首次出现的指定元素。
remove(Object o);
//返回列表中包含指定元素的结果。
contains(Object o);
//返回首次出现的指定元素的索引。
indexOf(Object o);
//检查列表是否为空。
isEmpty();
//返回列表中的元素数量。
size();
//获取指定位置的元素。
get(int index);
//替换指定位置的元素。
set(int index, E element);
----分割线----
3.セット
HashSetクラスを実装する
HashSet は、Set インターフェイスを実装する Java のデータ構造です。Set は重複した要素の格納を許可しないコレクションであり、通常、基礎となる層はハッシュ テーブルをカプセル化します。
機能の概要
- 重複した要素の保存は許可されません。セット内の各要素は一意であり、重複した要素は許可されません。
- 順序なし: HashSet は順序なしセットです。つまり、格納された要素は特定の順序で格納されますが、要素の格納順序は要素の実際の順序とは関係ありません。
- 最下層はハッシュ テーブルをカプセル化します。HashSet はハッシュ テーブルに基づいて実装されるため、追加、削除、クエリなどの操作の時間計算量は通常 O(1) です。
- スレッドセーフ: HashSet には同期メカニズムがないため、スレッドセーフではありません。マルチスレッド環境では、複数のスレッドが同時に HashSet を変更すると、データの不整合が発生する可能性があります。
- null 値の保存を許可する: List とは異なり、Set では null 値の保存が許可されます。
HashSet の一般的な用途:
//添加元素:使用`add(E e)`方法向Set中添加元素。如果元素已经存在,会被忽略,因为Set不允许重复元素。
HashSet<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("cherry");
//删除元素:使用remove(Object o)方法从Set中删除指定元素。如果元素不存在,删除操作会返回false。
set.remove("banana");
//查询元素:使用contains(Object o)方法查询Set中是否包含指定元素。
boolean containsApple = set.contains("apple");
//获取元素个数:使用size()方法获取Set中的元素个数。
int size = set.size();
//清空Set:使用clear()方法移除Set中的所有元素。
set.clear();
//迭代Set:使用iterator()方法返回一个迭代器,可以用来遍历Set中的所有元素。注意,返回元素的顺序并不是特定的。
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
LinkedHashSet クラスを実装する
LinkedHashSet は HashSet のサブクラスであり、java.util パッケージの下に存在します。これは特別な種類の HashSet です。
機能の概要
-
順序性: LinkedHashSet 内の要素は順序付けされており、追加された順序で要素の順序が維持されます。これは、LinkedHashSet の基礎となるレイヤーがハッシュ テーブルとリンク リストを使用するためです。リンク リストは、要素が同じ順序で格納および取得されることを保証するために使用されます。
-
効率的なパフォーマンス: LinkedHashSet の基礎となる層はハッシュ テーブルを使用して要素を格納するため、挿入、削除、検索操作を O(1) の時間計算量内で実行できます。これにより、頻繁に挿入、削除、検索操作が必要な場合、LinkedHashSet のパフォーマンスが ArrayList よりも向上します。
-
重複要素は許可されません: HashSet と同様に、LinkedHashSet はセット内の重複要素を許可しません。重複した要素を追加した場合、1 つだけが保持されます。
-
スレッドアンセーフ: HashSet と同様に、LinkedHashSet はスレッドアンセーフです。
LinkedHashSet の一般的な使用法
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
// 添加元素
linkedHashSet.add("apple");
linkedHashSet.add("banana");
linkedHashSet.add("cherry");
linkedHashSet.add("apple"); // 重复元素,会被忽略
// 输出LinkedHashSet中的元素
for (String element : linkedHashSet) {
System.out.println(element);
}
//输出结果,其中LinkedHashSet是有序的,因此输出的元素顺序将与添加的顺序一致。
apple
banana
cherry
TreeSetクラスを実装する
TreeSet は Java のクラスです。これは java.util パッケージに属し、Set コレクションのサブクラスです。SortedSet インターフェイスを実装しているため、TreeSet 内の要素は常に昇順に配置されます。。TreeSet はバイナリ ツリーに基づいて実装されます。
機能の概要
- 順序性: TreeSet 内の要素は特定の順序で配置されます。この順序は、TreeSet の作成時に指定されたコンパレータ、または要素自体の自然な順序によって決まります。コンパレータが指定されていない場合は、要素自体の自然な順序が有効になります。
- 独自性: TreeSet では重複した要素を保存できません。
- スレッド非安全: TreeSet はスレッド安全メカニズムを提供していないため、マルチスレッド環境で使用する場合は追加の同期対策が必要です。
- 基礎となるデータ構造: TreeSet の最下層は、赤黒ツリー データ構造を使用します。赤黒ツリーは、挿入、削除、検索操作を O(log n) の時間計算量で完了できる自己平衡型二分探索ツリーです。
TreeSet は、要素の自然な順序、または TreeSet の作成時に提供されるコンパレータによって定義された順序に従って走査されます。TreeSet もソートに使用できますが、要素を挿入するたびに二分探索が必要であり、時間計算量が O(log n) であるため、ArrayList より効率が低くなります。
TreeSet の一般的な使用法
//添加元素:使用add()方法向TreeSet中添加元素。
TreeSet<Integer> treeSet = new TreeSet<>();
treeSet.add(1);
treeSet.add(2);
treeSet.add(3);
//删除元素:使用remove()方法从TreeSet中删除元素。
treeSet.remove(2); // 从TreeSet中删除2
//查找元素:使用contains()方法查找TreeSet中是否包含指定元素。
boolean contains = treeSet.contains(1); // 返回true
//获取元素:使用first()方法获取TreeSet中的最小元素,使用last()方法获取TreeSet中的最大元素。
int first = treeSet.first(); // 返回TreeSet中的最小元素
int last = treeSet.last(); // 返回TreeSet中的最大元素
//清空TreeSet:使用clear()方法清空TreeSet中的所有元素。
treeSet.clear(); // 清空TreeSet
//遍历TreeSet:for-each循环遍历TreeSet中的所有元素。
for (Integer num : treeSet) {
System.out.println(num);
}
//遍历TreeSet:迭代器遍历TreeSet中的所有元素。
Iterator<Integer> iterator = treeSet.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
import java.util.Set;
import java.util.TreeSet;
/**
* TreeSet进行排序需要实现两个步骤:
* 1.实现Comparable接口
* 2.重写该接口中的compareTo方法,就是重写排序规则
*/
public class TreeSet {
public static void main(String[] args) {
Set<Dog> set = new TreeSet<>();
set.add(new Dog("nn",10));
set.add(new Dog("bb",9));
set.add(new Dog("hh",7));
set.add(new Dog("pd",8));
set.toString();
System.out.println(set);
}
}
//实现Comparable接口
class Dog implements Comparable<Dog>{
String name;
int age ;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public Dog() {
}
//重写排序规则
@Override
public int compareTo(Dog o) {
return this.age - o.age;
}
@Override
public String toString() {
return "Dog{" + name + "," + age + "}";
}
}
//输出:[Dog{hh,7}, Dog{pd,8}, Dog{bb,9}, Dog{nn,10}]
----分割线----
4. 待ち行列
キューは、先入れ先出し (FIFO) 原則に従う特別なデータ構造です。Queue インターフェースは Java の java.util パッケージに含まれており、Collection インターフェースのサブインターフェースです。
キュー機能の概要
- キューは、先入れ先出し (FIFO) 原則に従う線形構造です。つまり、最初にキューに入った要素が最初に削除されます。
- キューでは、テーブルのフロントエンド (前部) での削除操作と、テーブルのバックエンド (後部) での挿入操作のみが許可されます。これにより、キューの順序性、つまりキュー内の要素の位置が変わらなくなることが保証されます。
- キューは動的割り当て戦略を使用し、必要に応じて拡張および縮小できるため、効率的な挿入および削除操作を実行できます。
- キューを使用して、印刷タスクの処理、メッセージ キューの実装、プロセス間通信などの特定のタスクを実装できます。
キューの一般的な使用法
import java.util.LinkedList;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
// 创建一个队列
Queue<String> queue = new LinkedList<>();
// 入队操作
queue.add("Apple");
queue.add("Banana");
queue.add("Cherry");
// 输出队列的大小
System.out.println(queue.size()); // 输出:3
// 出队操作
System.out.println(queue.poll()); // 输出:Apple
System.out.println(queue.poll()); // 输出:Banana
System.out.println(queue.poll()); // 输出:Cherry
// 检查队列是否为空
System.out.println(queue.isEmpty()); // 输出:true
}
}
キュートラバーサル
キューのようなデータ構造では、キューの要素を直接走査することはできません。これは、キューが先入れ先出し (FIFO) データ構造であり、キュー内の要素の位置が動的に変化するためです。要素がフェッチされると、その要素は後続の要素の位置情報を保持せずにキューから削除されます。
ただし、次の方法で間接的にキューの要素を反復処理することは可能です。
- foreach ループを使用して走査する
public class Main {
public static void main(String[] args) {
Deque<String> queue = new LinkedList<>();
queue.add("Apple");
queue.add("Banana");
queue.add("Cherry");
for (String item : queue) {
System.out.println(item);
}
}
}
- イテレータを使用したループスルー
public class Main {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
queue.add("Apple");
queue.add("Banana");
queue.add("Cherry");
Iterator<String> iterator = queue.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
キューのサブインターフェース: Deque (両端キュー)
Deque (両端キュー) は、キューのフロントエンドとバックエンドで挿入および削除操作を実行できるデータ構造です。Deque (両端キュー) は FIFO 原理をサポートしており、最も早く追加された要素が最初に削除されます。
import java.util.Deque;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
Deque<String> deque = new LinkedList<>();
// 在后端添加元素
deque.addLast("Apple");
deque.addLast("Banana");
deque.addLast("Cherry");
// 在前端添加元素
deque.addFirst("Orange");
// 打印 deque 的内容
System.out.println(deque); // 输出:["Orange", "Apple", "Banana", "Cherry"]
// 移除前端元素并打印其值
System.out.println(deque.removeFirst()); // 输出:Orange
System.out.println(deque); // 输出:["Apple", "Banana", "Cherry"]
// 移除后端元素并打印其值
System.out.println(deque.removeLast()); // 输出:Cherry
System.out.println(deque); // 输出:["Apple", "Banana"]
}
}
----分割线----
5. 注意事項:
上記では、追加、削除、検索、要素の取得、トラバースなどの操作を含む、Collection の一般的な使用法をいくつか紹介しました。Collection を使用する場合は、次の点に注意する必要があります。
- コレクションのタイプに注意してください: 各コレクション タイプには特定の用途と制限があるため、ニーズに応じて適切なコレクション タイプを選択する必要があります。例えば、ArrayListを使用する場合は容量不足に注意する必要があり、LinkedHashSetを使用する場合は要素の順序が保証できないことに注意する必要があります。
- NullPointerException を避ける: コレクションを使用して要素を格納する場合、NullPointerException のスローを避けるために、Null オブジェクトの格納を避ける必要があります。
- コレクションの走査中に変更を避ける: コレクションの走査中にコレクション要素を変更すると、ConcurrentModificationException が発生する可能性があります。走査プロセス中にコレクション要素を変更する必要がある場合は、Iterator のremove() メソッドを使用できます。
- コレクションの容量に注意する: ArrayList などの動的配列型のコレクションを使用する場合は、容量不足の問題に注意する必要があります。配列の容量がそれ以上の要素を収容するのに十分でない場合は、拡張方法を使用して容量を増やす必要があります。