記事ディレクトリ
1.基本的な知識
1.コレクションフレームワークインターフェイス
コレクションの基本インターフェース:コレクションとマップ
2.コレクションと配列の比較
-
アレイの特徴
- 配列は本質的に連続したメモリ空間であり、同じタイプの複数のデータを記録するために使用されます。
- 配列が宣言されると、メモリ空間が固定されます。
- 挿入および削除操作は不便であり、多数の要素を移動して効率が低すぎる可能性があります。
- 添え字アクセスをサポートし、ランダムアクセスを実現できます。
- 配列の要素は、基本データ型または参照データ型にすることができます。
-
コレクションの特徴
- メモリ空間は不連続になり、データタイプは異なる場合があります。
- コレクションのメモリ空間は動的に調整できます。
- コレクションの挿入と削除では、多数の要素を移動できません。
- 添え字アクセスを部分的にサポートしていますが、サポートしていないものもあります。
- コレクションの要素は参照データ型である必要があります
3.コレクションの一般的なメソッド
- 一般的なサンプルメソッド
// 添加
boolean add(e);
// 用于将参数指定集合中的所有元素放入当前集合中。
boolean addAll(Collection<? extends E> c);
// 用于从当前集合中删除参数指定的元素。
boolean remove(Object o);
// 用于从当前集合中删除参数指定集合中的所有元素。
boolean removeAll(Collection<?> c);
// 用于将当前集合中的所有元素移除。
void clear()
// 用于判断当前集合中是否包含参数指定的单个元素。(o==null ? e==null : o.equals(e))
boolean contains(Object o);
// 用于判断当前集合中是否包含参数指定集合中的所有元素。
boolean containsAll(Collection<?> c);
// 用于判断当前集合是否为空。
boolean isEmpty();
// 用于返回当前集合中元素的个数。
int size()
// 用于获取当前集合和参数集合的交集并保留到当前集合中。若当前集合中的内容发生了更改则返回true,否则返回false。
boolean retainAll(Collection<?> c);
- 一般的なクラスメソッド
// 将所有指定的元素添加到指定的集合。
static boolean addAll(Collection<? super T> c, T... elements);
// 将所有元素从一个列表复制到另一个列表中。
static void copy(List<? super T> dest, List<? extends T> src);
// 交换指定列表中指定位置的元素。
static void swap(List<?> list, int i, int j);
// 反转指定列表中元素的顺序。
static void reverse(List<?> list);
リストコレクション(強調)
-
基本的な概念
java.util.ListインターフェースはCollectionインターフェースのサブインターフェースであり、要素は順番に配置され、繰り返しが許可されます。このインターフェイスの主な実装クラスは、ArrayListクラス、LinkedListクラス、Stackクラス、Vectorクラスです。
- ArrayListクラスの最下層は動的配列を使用して実装されるため、追加や削除は不便であり、要素へのアクセスも便利です。
- LinkedListクラスの最下層はリンクリストを使用して実装されているため、追加や削除が簡単で、要素にアクセスするのも不便です。
- その中で、スタック(stack)クラスの最下層は動的配列を使用して実装され、LIFO(後入れ先出し)と呼ばれる後入れ先出し特性を持つデータ構造を記述するために使用されます。
- Vectorクラスの下部は動的配列を使用して実装されています。ArrayListクラスと比較すると、これは初期のクラスであり、スレッドセーフクラスに属しているため、効率は比較的低くなります。代わりに、ArrayListクラスを使用することをお勧めします。
-
一般的な方法
void add(int index, E element)
- 用于将元素element插入到当前集合中index指向的位置。
boolean addAll(int index, Collection<? extends E> c)
- 用于将集合c中所有元素插入到当前集合中index指向的位置。
E remove(int index)
- 用于将index位置的元素从当前集合移除。
- 返回被删除的元素值,下标不合理时会产生下标越界异常。
E set(int index, E element)
- 使用element元素替换当前集合中index位置的元素,返回被替换的元素。
E get(int index)
- 用于返回当前集合中下标为index位置的元素。
List<E> subList(int fromIndex, int toIndex)
- 用于返回当前集合中从fromIndex(包含)到toIndex(不包含)之间的部分视图。
- 返回的集合和当前集合共用同一块内存区域。
キューの一般的なメソッド
boolean offer(E e) - 将参数指定的元素e插入到当前队列的末尾。
- 若插入成功则返回true,否则返回false。
E poll() - 用于从当前队列的队首移除一个元素并返回。
- 若当前队列为空,则返回null。
E peek() - 用于获取当前队列的队首元素并返回。
- 若当前队列为空,则返回null。
第二に、一般的な問題
1. ArrayとArrayListの違いは何ですか?ArrayListの代わりにいつArrayを使用すればよいですか?
1.違い:
- 配列には基本的なデータ型とオブジェクト型を含めることができ、ArrayListにはオブジェクト型のみを含めることができます。
- Arrayのサイズは固定されており、ArrayListのサイズは動的に変化します。
- ArrayListは、addAll()、removeAll()、iterator()などのメソッドと機能を提供します。
2.
基本的なタイプのデータの場合、コレクションは自動ボクシングを使用してコーディングの作業負荷を軽減します。ただし、この方法は、固定サイズの基本的なデータ型を扱う場合は比較的低速です。
2.ハッシュとは何ですか?
- ハッシュは、通常、ハッシュ、ハッシュ、またはハッシュとしての音訳として変換され、ハッシュアルゴリズムを介して任意の長さの入力を固定長の出力に変換します。出力はハッシュ値です。
- 一般的なハッシュアルゴリズム:
- MD4、MD5、md5はMD4よりも複雑で、速度は遅いですが安全であり、反分析と反微分でより優れています。
- ハッシュテーブルの一般的に使用される構築方法:
- 直接アドレス指定方法:キーワードまたはキーワードの線形関数をハッシュアドレスとして使用します。
- 二乗法:キーの二乗の真ん中をハッシュアドレスとして使用します。
- 乱数方式:ランダム関数を選択し、キーのランダム関数をハッシュアドレスとして使用します。
- 除算剰余法:キーがハッシュテーブルの長さm以下の数値pで除算された後の剰余がハッシュアドレスです。
3. HashMapとConcurrentHashMapの基本原理
- HashMapはハッシュの原則に基づいており、put()およびget()メソッドを使用してオブジェクトを格納および取得します。キーと値のペアをput()メソッドに渡す
と、キーオブジェクトのhashCode()メソッドを呼び出してハッシュコードを計算し、値のオブジェクトを格納するバケットの場所を見つけます。
オブジェクトを取得するときは、キーオブジェクトのequals()メソッドを使用して正しいキーと値のペアを検索し、値オブジェクトを返します。
HashMapはリンクリストを使用して衝突の問題を解決します。衝突が発生すると、オブジェクトはリンクリストの次のノードに格納されます。
HashMapは、リンクされた各リストノードにキーと値のペアオブジェクトを格納します。 - HashMapは次のステートメントで同期できます。
- マップm = Collections.synchronizeMap(hashMap);
- 結論
HashtableとHashMapには、スレッドの安全性と速度といういくつかの大きな違いがあります。完全なスレッドセーフが必要な場合にのみHashtableを使用してください。Java5以降を使用している場合は、ConcurrentHashMapを使用してください。
JDK 7
- ハッシュマップ->配列+リンクリスト
- key-> key.hashcode()%array size->配列の添え字を取得し、取得した添え字の配列に値がある場合、一方向のリンクリストが導入されます。頭にすばやく挿入します。
- エントリへの参照は配列に格納され、エントリはKVのエンティティ、エントリ配列です
- 安全でないスレッド
- ハッシュテーブルとロックに同期を追加
- ConcurrentHashmap配列+リンクリスト
- セグメントロックセグメントは配列に格納されます。
セグメントはhashentry(エントリと同じ)配列を格納します。各セグメントは、ロックも制御できる再入可能ロックReentrantLockを継承します。複数の要素がロックを共有できます。
JDK 8
-
HashMap->配列+リンクリスト+赤黒木
-
concurrentHashmap
- JDK8のConcurrentHashMapは、JDK8 HashMapの実装を指します。これは、配列+リンクリスト+赤黒木実装を使用して、多数の内部CAS操作を設計します。
- JDK8はセグメントを完全に破棄し、ノードを採用しました。その設計アイデアは、JDK1.7のセグメント化ロックのアイデアではなくなりました。
- ノード:キー、値、およびキーハッシュ値を保持するデータ構造。valueとnextの両方が揮発性で変更され、同時可視性が確保されます。
- JDK8のConcurrentHashMapは、リンクリストの長さが特定のしきい値を超えると、リンクリストを赤黒ツリーに変換して、検索パフォーマンスをさらに向上させます。
- 概要:JDK8での実装はロック分離の概念でもあり、セグメント(JDK1.5)よりも細かくロックを分割します。ハッシュが競合しない限り、同時ロック取得はありません。
最初に、ロックフリー操作CASを使用してヘッドノードを挿入します。挿入が失敗した場合は、別のスレッドがヘッドノードに挿入されており、操作が再度繰り返されます。ヘッドノードが既に存在する場合、
同期によってヘッドノードロックが取得され、後続の操作が実行されます。セグメントセグメントロックよりもパフォーマンスが改善されました。
4.マップの分類と一般的な状況について話す
- Javaは、データ構造内のマッピング用のインターフェースjava.util.Mapを定義し、4つの実装クラス、つまりHashMap、Hashtable、LinkedHashMap、およびTreeMapを備えています。
- マップは主にヘルス値のペアを格納し、キーに従って値を取得するために使用されます。そのため、キーを繰り返すことはできません(重複が繰り返されます)が、値は繰り返すことができます。
- Hashmapは最も一般的に使用されるマップの1つです。キーのHashCode値に従ってデータを格納し、キーに従ってその値を直接取得できます。アクセス速度が高速です。走査するとき、データを取得する順序は完全にランダムです。HashMapでは、1つのレコードのキーのみをNullにすることができます。複数のレコードの値はNullです。HashMapはスレッドの同期をサポートしていません。つまり、複数のスレッドが同時にHashMapを書き込むことができるため、データの不整合が発生する可能性があります。同期が必要な場合は、コレクションのSynchronizedMapメソッドを使用して、HashMapが同期できるようにするか、ConcurrentHashMapを使用できます。
- HashtableはHashMapに似ており、Dictionaryクラスから継承しますが、違いは次のとおりです:レコードキーまたは値が空であることを許可しません。つまり、スレッドの同期をサポートします。つまり、いつでも
1つのスレッドだけがHashtable を書き込むことができるため、Hashtableも書き込みます。入場時間が遅くなります。 - LinkedHashMapはHashMapのサブクラスであり、レコードの挿入順序を保存します。Iteratorを使用してLinkedHashMapをトラバースする場合、最初に取得したレコードを最初に
挿入する必要があります。アプリケーションの数でソートするために、構築にパラメーターを使用することもできます。トラバース時の速度はHashMapよりも遅くなりますが、例外が1つあります
。HashMap の容量が大きく、実際のデータが小さい場合、LinkedHashMapのトラバース速度は実際のデータにのみ関連し、容量とは関係がないため、トラバースはLinkedHashMapよりも遅くなることがあります。
HashMapの走査速度は、彼の容量に関連しています。 - TreeMapは、保存したレコードをキーでソートできるSortMapインターフェースを実装しています。デフォルトでは、キー値を昇順でソートします。ソートコンパレーターを指定することもできます。イテレーターを使用し
てTreeMap をトラバースすると、取得されたレコードがソートされます。
- 一般的な状況
一般に、私たちはHashMapを最もよく使用し、マップ内の要素の挿入、削除、および検索を行います。HashMapが最良の選択です。ただし、キーを自然順序またはカスタム順序でトラバースする場合は、TreeMapの方が適しています。入力と同じ順序で出力する必要がある場合は、LinkedHashMapを使用できます。また、読み取り順に配置することもできます。- HashMapは最も一般的に使用されているマップの1つであり、キーのhashCode値に従ってデータを格納し、アクセス速度が速く、キーに従ってその値を直接取得できます。HashMapでは、1つのレコードのキーのみを最大でNULLにすることができ、複数のレコードの値をNULLにすることができます。HashMapはスレッドの同期をサポートしていません。つまり、複数のスレッドが同時にHashMapを書き込む可能性があり、データの不整合が発生する可能性があります。同期する必要がある場合は、コレクションのSynchronizedMapメソッドを使用して、HashMapに同期機能を持たせることができます。
- HashtableはHashMapに似ていますが、記録されたキーまたは値を空にすることができない点が異なります。これは、スレッドの同期をサポートします。つまり、一度に1つのスレッドしかHashtableに書き込めないため、書き込み時にHashtableが遅くなります。
- LinkedHashMapはレコードの挿入順序を保存します。Iteratorを使用してLinkedHashMapを反復処理する場合、最初に取得したレコードを最初に挿入する必要があります。
- トラバースする場合、HashMapよりも遅くなります。TreeMapでは、保存したレコードをキーに従って並べ替えることができます。デフォルトでは、昇順で並べ替えられます。並べ替えコンパレータを指定することもできます。Iteratorを使用してTreeMapをトラバースすると、結果のレコードがソートされます。
5.マップをトラバースする方法
- 最も一般的
for (Map.Entry<Object, Object> entry : map.entrySet()) {
System.out.println("key=" + entry.getKey() + ",value=" + entry.getValue());
}
- キーまたは値のみが必要な場合
// 遍历key 使用 keySet()
for (String key : map.keySet()) {
System.out.println("key=" + key);
}
// 遍历value 使用 values()
for (Object value : map.values()) {
System.out.println("value=" + value);
}
- イテレーターを使用してマップをトラバースする
ヒント:トラバーサル中の削除操作中は、イテレータートラバーサルメソッドのみを使用できます。他のトラバーサルは例外をスローします(ちなみに、リストをトラバースして、Iteratorメソッドを介して削除操作を完了することができ、リストの削除メソッドを直接呼び出すと、例外がスローされます)。
Iterator<Map.Entry<String, Object>> entries = map.entrySet().iterator();
while (entries.hasNext()) {
Entry<String, Object> entry = entries.next();
System.out.println("key=" + entry.getKey() + ",value=" + entry.getValue());
}
- キーをたどって値、欠点、低効率を見つけることは、キー自体からの値自体が時間のかかる操作です。
for (String key : map.keySet()) {
Object value = map.get(key);
System.out.println("key=" + key + ",value=" + value);
}
最後に書く
この記事があなたに役立つと思うなら、あなたは私にほめ言葉を与えることができます。あなたの注意とサポートが私の最大の励ましです。
記事に提案やコメントがある場合は、メッセージを残して教えてください。フィードバックをお待ちしています。