目次
コレクションのクラス図
UML クラス図には、いくつかの共通の関係があります。
一般化:サブクラスが親クラスのすべての特徴的な動作をどのように特殊化するかを指定する、一般的および特別な関係を表す継承関係です。例:トラは動物の一種です。つまり、トラの特徴にも動物の共通点があります。
実装:クラスとインターフェースの関係。インターフェースのすべての機能と動作の実装を表します。
関連付け: あるクラスが別のクラスのプロパティとメソッドを知ることができるようにする所有関係です. 関連付けは双方向と一方向に分けられます. たとえば、教師と生徒は双方向の関係にあり、教師には複数の生徒がいて、生徒には複数の教師がいる場合があります。ただし、学生とコースの関係は一方通行であり、学生は複数のコースを受講する場合があります。コースは抽象的なものであり、学生を所有するものではありません。
集合体:全体と部分の関係、部分は全体から独立して存在できる。例: 車とタイヤは部品全体の関係であり、タイヤは車から離れても存在できます。
コンビネーション:全体と部分の関係で、会社がなければ部門もありません。合成関係は一種の関連関係であり、集合関係よりも強い関係であり、通常の集合関係で全体を表すオブジェクトが、部分を表すオブジェクトのライフサイクルに責任を負う必要があります。
依存関係: これは使用の関係です。つまり、あるクラスの実装には別のクラスの支援が必要なので、双方向の相互依存関係を使用しないようにしてください。
関係の強い順序と弱い順序:一般化 = 実現 > 構成 > 集約 > 関連 > 依存関係
リスト コレクション
リスト コレクションの機能: 要素は順序付けられ、反復可能です
トラバーサル メソッド: subscript、foreach、iterator
リスト コレクションの実装メソッド: ArrayList、LinkedList、Vector、CopyOnWriteArrayList
junit testを使用すると、コードはより簡単になります
基本トラバーサルループ方式
@Test
public void listAdd() {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(3);
list.add(5);
list.add(4);
System.out.println(list);
}
private List<Integer> list = new ArrayList<>();
@Before
public void setup() {
list.add(1);
list.add(3);
list.add(5);
list.add(4);
}
// 第一种遍历方法
@Test
public void list1() {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
//第二种遍历方法
@Test
public void list2() {
for (Integer integer : list) {
System.out.println(integer);
}
}
//迭代器
@Test
public void list3() {
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
ArrayList は最も一般的に使用されるコレクションです
特徴: 1. シンプルなデータ構造、容量を超えた自動拡張、動的配列
2、内部実装は基礎となるオブジェクト配列に基づいています
3.高速ランダムアクセス
短所: 1. ランダムな追加または削除には適していません。
2、スレッドが安全でない
リストされたリスト
機能: 1. LinkedList は、追加の get、remove、および insert メソッドを LinkedList の先頭または末尾
に提供します 2. LinkedList は、スタック (プッシュ、ポップ メソッドを含む)、キュー (キュー)、または双方向キュー (デキュー) として使用できます
3. 二重連結リストで実装されているため、連結リストには容量制限がなく、要素を null にすることができ、スレッドセーフではありません
4. ランダムな追加または削除に適していますベクター
Vector の内部実装は ArrayList に似ています。スレッド同期をサポートし、一度に 1 つのスレッドのみが Vector に書き込むことができます。ただし、コストが高いため、Vector へのアクセスは ArrayList へのアクセスよりも遅くなります。(スレッドセーフ、遅い並列パフォーマンス)
CopyOnWriteArrayList
機能: 1. コピー オン ライト
2. スレッド セーフ
3. 読み取りが多く、書き込みが少ないシナリオに適してい
ます 4. 書き込み時に新しい配列をコピーし、操作の挿入、変更、または削除後に新しい配列を配列に割り当て
ます 5. より高いベクトルよりもパフォーマンス
6、結果整合性
7、List インターフェイスを実装し、ArrayList と同様の方法で使用されます。
ArrayListdelete メソッド
package com.zking.list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
public class ListDamo2 {
private List<Integer> list;
@Before
public void setup() {
list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(3);
list.add(4);
}
// 下标循环删除方式1
@Test
public void remove1() {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 3)
list.remove(i);
}
System.out.println(list);
}
// 下标循环删除方式2
@Test
public void remove2() {
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == 3)
list.remove(i--);
}
System.out.println(list);
}
// 下标循环倒序删除
@Test
public void remove3() {
for (int i = list.size() - 1; i >= 0; i--) {
if (list.get(i) == 3)
list.remove(i);
}
System.out.println(list);
}
// foreach循环删除
@Test
public void remove4() {
for (Integer integer : list) {
if (integer == 3)
list.remove(integer);
}
System.out.println(list);
}
// 第五种删除方法
@Test
public void remove5() {
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
if (it.next() == 3) {
it.remove();
}
}
System.out.println(list);
}
// 第六种删除方法
@Test
public void remove6() {
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
Integer value = it.next();
if (value == 3) {
list.remove(value);
}
}
System.out.println(list);
}
// 删除的参数是基本型的函数
@Test
public void remove7() {
list.remove(2);
System.out.println(list);
}
}
セットコレクション
コレクション機能の設定: 要素は順序付けられておらず、繰り返されません
トラバーサル メソッド: foreach、イテレータ
セットコレクションの実装方法:Hashset、TreeSet
一意の要素を格納し、null 値を許可します (オブジェクトのハッシュコードに従って要素が存在する
かどうかを判断します) オブジェクトのハッシュコードに従って要素が存在するかどうかを判断します
HashMap によってバックアップされ
ます 挿入順序を維持し
ません スレッドセーフではありません
問題について考えていますか?
1. リスト コンテナ内の要素を重複排除する方法は?
2. ArrayList コレクションを重複排除する方法
最初に重複リストを HashSet にスローし、HashSet を使用して重複データを削除してから、HashSet を介して新しい ArrayList を見つけます。
public class SetDamo { private List<Integer> list = new ArrayList<>(); @Before public void setup() { list.add(1); list.add(1); list.add(2); list.add(2); list.add(3); list.add(3); } @Test public void set1() { List<Integer> list2 = new ArrayList<>(new HashSet<Integer>(list)); System.out.println(list2); }
結果は次のとおりです。
3. set は ArrayList の添え字による削除、または foreach ループによる削除の問題を抱えていますか? どうして
set は順序付けられていないコレクションであり、添字なしです。添字で取得する方法はありません。foreach ループまたは反復子を介してのみです。
4. セットにはリストの削除がありますか? 入ってくる整数は、基本タイプまたはオブジェクト タイプと区別する必要があります。例: list.remove(Integer.valueof(2)); はオブジェクト型です。
list.remove(2); は基本型です
どちらも結果が違う
ただし、セット コレクションには添え字がなく、オブジェクトを介して直接削除されます
5. HashSet はどのように実装されますか?map による実装 map はキーと値のペアであるため、キーを繰り返すことはできませんが、値を繰り返すことはでき、値はキーに格納されます。キーのみが使用され、実行時に値は使用されません
学生クラスを書く
package com.zking.set; public class Student { private Integer sid; private String sname; private Integer age; public Student(Integer sid, String sname, Integer age) { super(); this.sid = sid; this.sname = sname; this.age = age; } public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((age == null) ? 0 : age.hashCode()); result = prime * result + ((sid == null) ? 0 : sid.hashCode()); result = prime * result + ((sname == null) ? 0 : sname.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age == null) { if (other.age != null) return false; } else if (!age.equals(other.age)) return false; if (sid == null) { if (other.sid != null) return false; } else if (!sid.equals(other.sid)) return false; if (sname == null) { if (other.sname != null) return false; } else if (!sname.equals(other.sname)) return false; return true; } @Override public String toString() { return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]"; } }
public class SetDamo { @Test public void set2() { Set<Student> stu = new HashSet<>(); stu.add(new Student(1, "hh", 18)); stu.add(new Student(1, "hh", 18)); stu.add(new Student(2, "aa", 19)); stu.add(new Student(2, "aa", 19)); for (Student student : stu) { System.out.println(student); } } }
結果は次のとおりです。
TreeSet コレクションの特徴: 要素は順序付けられており、繰り返しはありません
機能: 順序付けられた Set コレクションを提供し、自然な並べ替えまたは提供された Comparator に従って並べ替えます。
TreeSet は TreeMap に基づいて実装されます。
- HashSet コレクションは順序付けされておらず、場合によっては順序付けられたコレクションが必要になります。その場合は TreeSet を使用できます。
- TreeSet を使用してオブジェクトを格納する場合、add() メソッドは比較のために自動的に compareTo() メソッドを呼び出します。
- 比較結果に応じて二分木形式で格納します。(TreeSet は TreeMap を使用して直接実装されます)
自然な並べ替え:
//如果保存的是数值型,则按数值排序 @Test public void set4() { TreeSet<Integer> set=new TreeSet<>(); set.add(4); set.add(2); set.add(3); set.add(1); System.out.println(set); } //如果保存的是字符,则按字符对应的ASCII进行排序 @Test public void demo2() { TreeSet<String> ts = new TreeSet<>(); ts.add("a"); ts.add("d"); ts.add("b"); ts.add("c"); System.out.println(ts); }
コンパレータソート_
TreeSet は、コンストラクターを介してコンパレーターを渡します
@Test public void set4() { TreeSet<Integer> set = new TreeSet<>(new Comparator<Integer>() { // 比较方法 @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } }); set.add(4); set.add(2); set.add(3); set.add(1); System.out.println(set); }
操作結果:
並べ替えインターフェイスを実装する
@Test public void set6() { TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() { // 比较方法 @Override public int compare(Student o1, Student o2) { return o2.getAge() - o1.getAge(); } }); set.add(new Student(1, "aa", 18)); set.add(new Student(2, "bb", 19)); set.add(new Student(3, "cc", 20)); set.add(new Student(4, "dd", 21)); for (Student student : set) { System.out.println(student); } }
インターフェイスを実装する Student クラスを作成する
package com.zking.set; public class Student implements Comparable<Student>{ private Integer sid; private String sname; private Integer age; public Student(Integer sid, String sname, Integer age) { super(); this.sid = sid; this.sname = sname; this.age = age; } public Integer getSid() { return sid; } public void setSid(Integer sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((age == null) ? 0 : age.hashCode()); result = prime * result + ((sid == null) ? 0 : sid.hashCode()); result = prime * result + ((sname == null) ? 0 : sname.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age == null) { if (other.age != null) return false; } else if (!age.equals(other.age)) return false; if (sid == null) { if (other.sid != null) return false; } else if (!sid.equals(other.sid)) return false; if (sname == null) { if (other.sname != null) return false; } else if (!sname.equals(other.sname)) return false; return true; } @Override public String toString() { return "Student [sid=" + sid + ", sname=" + sname + ", age=" + age + "]"; } @Override public int compareTo(Student o) { if (this.getAge()==o.getAge()) { return o.getSid()-this.getSid(); } return o.getAge()-this.getAge(); } }
@Test public void set6() { TreeSet<Student> set = new TreeSet<>(); set.add(new Student(1, "aa", 18)); set.add(new Student(5, "ee", 18)); set.add(new Student(2, "bb", 19)); set.add(new Student(3, "cc", 20)); set.add(new Student(4, "dd", 21)); for (Student student : set) { System.out.println(student); } }
操作結果:
マップ コレクション
マップ コレクションの機能: 順序付けされていない、キーと値のペアである、キーを繰り返すことができない、値を繰り返すことができる; キーが繰り返される場合、上書きされ、コレクション インターフェイスは継承されません
トラバーサル メソッド: 最初にすべてのキーの Set コレクションを取得し、次にトラバース (キーを介して値を取得)、すべてのエントリを保持するセットを取り出し、次にセットをトラバースします。
Map コレクションの実装メソッド: HashMap、HashTable、ConcurrentHashMap、TreeMap、LinkedHashMap
HashMap コレクションの機能: スレッドセーフでない、最も一般的に使用される、高速; データを格納するための配列の内部使用
基本原則:実行プロセスを置く
テーブル配列内のノード
連結リスト構造の模式図
赤黒木構造の模式図
フローチャートの緑で囲んだ部分がJDK8の新しい処理ロジックで、Table[i]のNodeノード数が8以上の場合に赤黒木による検索速度を向上させることを目的としています。
public class MapDamo { private Map<String, Object> map = new HashMap<>(); @Before public void setup() { map.put("1", "aa"); map.put("1", "aa"); map.put("2", "bb"); map.put("3", "cc"); map.put("4", "dd"); } @Test public void map1() { Iterator<String> it = map.keySet().iterator(); while (it.hasNext()) { String key = it.next();// 获取键 String object = (String) map.get(key);// 获取值 System.out.println(object); } } @Test public void map2() { Iterator<Entry<String, Object>> it = map.entrySet().iterator(); // 遍历所有集合 while (it.hasNext()) { Entry<String, Object> entry = it.next(); System.out.println("key=" + entry.getKey() + " value=" + entry.getValue()); } }
- map1 がループするとき、キーの値は同じで、背面が前面を覆っています
- map2 エントリは、エンティティ オブジェクトに 2 つの値 (キー、値) を含むエンティティとして理解できます。
HashTable: スレッド セーフ、あまり使用されない
@Test public void map3() { Map<String, Object> table = new HashMap<>(); table.put("1", "aa"); table.put("1", "bb"); table.put("2", "cc"); table.put("3", "dd"); Iterator<String> it = table.keySet().iterator(); while (it.hasNext()) { String key = it.next(); System.out.println(table.get(key)); } System.out.println("------------"); Iterator<Entry<String, Object>> it1 = table.entrySet().iterator(); while (it1.hasNext()) { Entry<String, Object> entry = it1.next(); System.out.println("key=" + entry.getKey() + " value=" + entry.getValue()); } }
操作結果:
ConcurrentHashMap: スレッドセーフ、HashTable よりも高いパフォーマンス
@Test public void map4() { Map<String, Object> map = new ConcurrentHashMap<>(); map.put("1", "aa"); map.put("1", "bb"); map.put("2", "cc"); map.put("3", "dd"); map.put("4", "ee"); Iterator<String> it = map.keySet().iterator(); while (it.hasNext()) { String key = it.next();// 获取键 String object = (String) map.get(key);// 获取值 System.out.println(object); } }
操作結果:
TreeMap: キー値は特定の順序でソートされます; 要素を追加または取得するときのパフォーマンスは HashMap よりも遅くなります; キー値の順序を保証するために内部の赤黒ツリーを維持する必要があるためです@Test public void map5() { TreeMap<Integer, String> treeMap = new TreeMap<>(new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o1-o2; } }); treeMap.put(1, "zs"); treeMap.put(2, "ls"); treeMap.put(3, "ww"); Iterator<Integer> it = treeMap.keySet().iterator(); while (it.hasNext()) { Integer key = it.next();// 获取键 String object = (String) treeMap.get(key);// 获取值 System.out.println(object); } }
操作結果:
LinkedHashMap 機能: HasMap コレクションを継承します; 順序付けられ、挿入順序にデフォルト設定されます; キー値を順序どおりに保存する場合は、LinkedHashMap を使用する必要があります
@Test public void map6() { Map<String, String> linkedHashMap = new LinkedHashMap<>(); linkedHashMap.put("1", "张三"); linkedHashMap.put("2", "李四"); linkedHashMap.put("3", "王五"); Set<Entry<String, String>> set = linkedHashMap.entrySet(); Iterator<Entry<String, String>> iterator = set.iterator(); while (iterator.hasNext()) { Entry entry = iterator.next(); String key = (String) entry.getKey(); String value = (String) entry.getValue(); System.out.println("key:" + key + ",value:" + value); } }
操作結果: