Collection: コレクション List、Set、Queue の最も基本的なインターフェース
マップ: マッピング テーブルの基本的なインターフェイス
イテレータ: コレクション内のデータをトラバースできるイテレータ
(注: 下図に誤りがあります。ArrayList を展開すると、容量が 1.5 倍に拡張されます)
リスト
リストは順序付けられたコレクションです。Java List には、ArrayList、Vector、および LinkedList の 3 つの実装クラスがあります。
ArrayList は最も一般的に使用される List 実装クラスです. 配列を介して内部的に実装されます. ランダム検索とトラバーサルには適していますが, 挿入と削除には適していません (より高価です)
実装原理: 配列、容量が足りない場合、新しい容量配列を作成し、arraycopy を使用して元の配列をコピーします
ベクター
ArrayList と同様に、配列を介して実装されます。違いは、スレッド同期をサポートすることです。一度に 1 つのスレッドのみが Vector に書き込むことができるため、複数のスレッドによる同時書き込みによる不一致を回避できますが、同期には高いコストが必要です。したがって、アクセスは遅くなります。
リンクされたリスト
連結リストによるデータの格納は動的な挿入や削除に適しており、ランダムアクセスやトラバーサルの速度が遅い. また、List インタフェースで定義されていない、特にヘッダーを操作するために使用されるメソッドも提供する.およびテール要素であり、スタックおよびキューとして使用でき、双方向キューが使用されます。
設定
セットは乱雑に保管されており、繰り返すことはできません。オブジェクトの等価性の本質は、hashCode 値 (メモリ アドレスに基づいて Java によって計算されたシリアル番号) です。
HashSet (ハッシュテーブル)
HashSet の格納要素は、順序どおりに格納されるのではなく、ハッシュ値に従って取得され、要素のハッシュ値は hashcod メソッドを介して取得されます。HashSet は、まず 2 つの要素のハッシュ値を判定し、ハッシュ値が同じ場合は equals メソッドで比較し、equls の結果が true の場合、HashSet は同じ要素と見なされます。equals が false の場合、同じ要素ではありません。
ハッシュ値が同じ場合、図に示すように、同じハッシュ値で拡張されます。
HashSet は、メモリ内の要素の場所を hashCode 値によって決定します。1 つの hashCode 位置に複数の要素を格納できます
TreeSet (二分木)
TreeSet() は、二分木の原理を利用して、new add() のオブジェクトを指定された順序 (昇順、降順) でソートすることです. オブジェクトが追加されるたびに、それはソートされ、オブジェクトはバイナリ ツリーの指定された位置に挿入されます。(順不同、繰り返し不可)
LinkHashSet(HashSet+LinkedHashMap)
HashSet を継承し、LinkedHashMap に基づいて実装されています。LinkedHashSet の最下層は LinkedHashMap を使用してすべての要素を保存します. HashSet から継承し, そのすべてのメソッドは HashSet と同じように動作します. したがって, LinkedHashSet の実装は非常に簡単です. 4 つの構築メソッドを提供するだけで, 識別パラメータを渡すことによって, 親を呼び出す クラスのコンストラクタは最下層に LinkedHashMap を構築することで実装されます. 関連する操作は親クラスの HashSet と同じで, 親クラスの HashSet のメソッドを直接呼び出すだけです.
地図
HashMap (配列 + リンク リスト + 赤黒木)
HashMap は、キーの hashCode 値に従ってデータを格納します. ほとんどの場合、その値は直接配置できるため、アクセス速度は高速ですが、走査順序は不確実です. HashMap では、1 つのレコードのキーのみを null にすることができ、複数のレコードの値を null にすることができます。HashMap はスレッドセーフではありません。つまり、複数のスレッドがいつでも同時に HashMap に書き込むことができるため、データの不整合が生じる可能性があります。スレッド セーフが必要な場合は、Collections の synchronizedMap メソッドを使用して HashMap をスレッド セーフにするか、ConcurrentHashMap を使用できます。次の図を使用して、HashMap の構造を紹介します。
HashMap の内部には配列があり、配列内の各要素は一方向リンク リストです。上の図では、緑色の各エンティティはネストされたクラス Entry のインスタンスであり、Entry にはキー、値、ハッシュ値、および一方向リンク リストの次の 4 つの属性が含まれています。
1. 容量: 常に 2^n である現在の配列容量を拡張できます. 拡張後、配列サイズは現在のサイズの 2 倍になります.
2. loadFactor: 負荷係数。デフォルトは 0.75 です。
3. しきい値: 拡張のしきい値、容量 * 負荷係数に等しい
JAVA8の実装
Java8 は HashMap にいくつかの変更を加えました. 大きな違いは、赤黒木を使用することで、配列 + 連結リスト + 赤黒木で構成されます。
Java7 HashMap の導入によると、検索時に、ハッシュ値に従って配列の特定の添字をすばやく見つけることができることはわかっていますが、その後、必要なものを見つけるために、リンクされたリストに沿って 1 つずつ比較する必要があります。 . 時間計算量は、リンクされたリストの長さが O(n) に依存します。この部分のオーバーヘッドを削減するために、Java8 では連結リストの要素数が 8 を超えると連結リストが赤黒木に変換され、時間の複雑さを O(logN) に減らすことができます。これらの位置で検索する場合。
HashTable (スレッドセーフ)
Hashtable はレガシー クラスです. マッピングの多くの一般的な関数は HashMap に似ています. 違いは、それが Dictionary クラスから継承され、スレッドセーフであることです. 一度に 1 つのスレッドだけが Hashtable に書き込むことができます. 同時実行性はそれほど良くありません. ConcurrentHashMap はセグメンテーション ロックを導入するため、ConcurrentHashMap として。Hashtable を新しいコードで使用することはお勧めしません. スレッド セーフが必要ない場合は HashMap に置き換えることができ, スレッド セーフが必要な場合は ConcurrentHashMap をスレッド セーフに置き換えることができます.
TreeMap (ソート可能)
TreeMap は SortedMap インタフェースを実装しています.これは,キーに従って保存したレコードをソートできます.デフォルトはキー値の昇順です.ソートコンパレータを指定することもできます.Iterator を使用して TreeMap をトラバースする場合,取得したレコードはソートされます. .
ソートされたマップを使用する場合は、TreeMap をお勧めします。
TreeMap を使用する場合、キーは Comparable インターフェースを実装するか、TreeMap の構築時にカスタム Comparator を渡す必要があります。そうしないと、タイプ java.lang.ClassCastException の例外が実行時にスローされます。
LinkHashMap (レコード挿入順)
LinkedHashMap は HashMap のサブクラスであり, レコードの挿入順序を保存します. Iterator を使用して LinkedHashMap をトラバースする場合, 最初に取得したレコードを最初に挿入する必要があります. アクセス順序に従ってソートされたパラメータで構築することもできます.
面接の質問
1. ArrayList と Vector の違い
どちらのクラスも List インターフェイスを実装しており、繰り返すことができる順序付けられたコレクションです。
この 2 つの違いは、主に次の 2 つの部分にあります。
同期: Vector はスレッドセーフであり、そのスレッドが同期されていることを示しますが、ArrayList はスレッドセーフではなく同期されていません。1 つのスレッドのみがアクセスする場合は、スレッド セーフを考慮せずに ArrayList を使用する方が効率的です。複数のスレッドがコレクションにアクセスし、考慮せずに Vecctor を使用し、スレッド セーフなコードを記述します。
データの増加: 両方とも初期容量があり、容量が不足すると、Vector は毎回元のサイズを 2 倍にし、ArrayList はデフォルトで元のサイズの 1.5 倍に増加します。ArrayList と Vector はどちらも初期スペース サイズを設定でき、Vector は拡張スペース サイズも設定できます
が、ArrayList は拡張スペースを設定するメソッドを提供しません。
2. ArrayList、Vector、LinkedList のストレージ性能と特徴について話す
ArrayList と Vector はどちらも配列を使用してデータを格納します. この配列の要素の数は, 要素を
追加および挿入するために実際に格納されたデータよりも大きくなります. どちらもシリアル番号で要素に直接インデックスを付けることができますが, 要素の挿入には
配列の移動などのメモリ操作が必要です.ベクトルは
同期方式 (スレッド セーフ) を使用するため、データのインデックス作成は高速ですが、データの挿入は低速です。
通常、パフォーマンスは ArrayList よりも劣りますが、LinkedList はストレージに二重連結リストを使用します. シリアル番号によるデータのインデックス作成には
前後のトラバーサルが必要ですが、データを挿入する場合は、このアイテムの前後のアイテムを記録するだけで済みます
。挿入速度が速くなります。
ArrayList は検索が高速で、LinkedList は挿入と削除の際により多くの利点があります。
3. フェイルファストとフェイルセーフの違いは何ですか?
Iterator のフェイルセーフは、基になるコレクションのコピーを作成することに基づいているため、ソース コレクションの変更の影響を受けません。
パッケージ java.util の下のすべてのコレクション クラスはフェイルファストですが、
パッケージ java.util.concurrent の下のすべてのクラスはフェイル セーフです。失敗-高速反復子は
ConcurrentModificationException をスローしますが、フェイルセーフ反復子は決してスローしません
4. ハッシュマップのデータ構造
(Javaプログラミング言語でのデータ構造は配列と連結リストのみ) HashMapは配列と連結リストを組み合わせて使うことを連結リストハッシング(ハッシング)と呼ぶ
5. HashMap の動作原理は何ですか?
HashMap は、キーと値のペアの形式で要素を格納します。HashMap には、 hashCode() および equals() メソッドを使用して要素をコレクションに追加および取得するハッシュ関数が必要です。put メソッドを呼び出すと、hashMap がキーのハッシュ値を計算し、キーと値のペアを適切なインデックスに格納します。キーがそこにない場合、値は新しい値に更新されます。HashMap のいくつかの重要な機能は、その容量、負荷係数、およびしきい値のサイズ
変更です。
6. Hashmap はいつ拡張されますか?
ハッシュマップ要素の数が配列サイズのloadFactorを超えると、配列が拡張されます.デフォルトのloadFactorは0.75で、デフォルトの配列サイズは16です.数が12を超えると、2倍になり、各要素を再計算します.配列の位置。
7. 要素にアクセスする際の List、Map、Set の 3 つのインターフェースの特徴は?
まず、List と Set はどちらも単一列要素のコレクションであり、それらの親インターフェイスは Collection です。Set は要素の繰り返しを許可しない、つまり 2 つの等しい要素 (equals) が存在できないため、set コレクション メソッドには、等しいかどうかを判断するブール値の戻り値があります. Set コレクションは順序付けられておらず、任意に取り出すことはできません. イテレータ要素を繰り返し使用できます。List は順序付けられたコレクションを表し、add によって追加された順序に従って、指定されたインデックスはオブジェクト全体を指し、任意にオブジェクトを取り出すことができます。
第二に、Map は List や Set とは異なります. 2 列のコレクションです. キー/値の格納には put メソッドが使用されます, 同じキー値を格納することはできません. 繰り返されるルールも equals によって判断されます. 同時に時間、すべてのキー値または値を個別に取り出すことができます. , 複合値を取得することもできます (Map.Entry).
リストは特定の順序で要素を保持し、要素が重複している可能性があります。セットは重複する要素を持つことはできません。内部順序付けです。
マップはキーと値の値を保存し、値は複数の値を持つことができます
(HashSet は、hashCode 値のサイズに直接基づくのではなく、hashcode 値の特定の計算方法に従って格納されます 。)
8. Set 内の要素は繰り返すことができないため、繰り返されているかどうかを区別するためにどの方法が使用されますか? == または equals() ですか
? それらの違いは何ですか?
要素が繰り返されるかどうかを判断するには、equals を使用して判断します。
- == は 2 つの変数またはインスタンスが同じメモリ空間を指しているかどうかを判断するものであり、equals は 2 つの変数またはインスタンスが指すメモリ空間の値が同じであるかどうかを判断するものです。
- == はメモリアドレスの比較を指し、 equals() は文字列の内容を比較します
- == は使い方が同じかどうか、equals() は値が同じかどうかを示します
9. 2 つのオブジェクトは同じ値 (x.equals(y) == true) を持ちますが、異なるハッシュ コードを持つことができます. この文は正しいですか?
右。オブジェクトが HashSet または HashMap に格納される場合、それらの等号は等しく、それらの
ハッシュコード値は等しくなければなりません。
HashSet や HashMap に保存しないのであれば, ハッシュコードとは関係ありません. 現時点では,
異なるハッシュコードを持つことが可能です. 例えば, arrayList に格納されたオブジェクトはハッシュコードを実装する必要はありません.
もちろん実装しない理由はなく、通常は実装しています。
10.ヒープとスタックの違いは何ですか
Java メモリは、スタック メモリとヒープ メモリに分割されます。スタック メモリとは、プログラムがメソッドに入った後、このメソッドがメソッド内のローカル変数を格納するための別のストレージ スペースが開かれることを意味します。メソッドが終了すると、メモリは解放されます。ヒープ メモリは、新しいオブジェクトなど、メソッド スタックに配置されていないデータを格納するために使用されます。ローカル変数は、final で変更された後にヒープに配置されます。
11. Java コレクション クラス フレームワークの基本的なインターフェイスは何ですか?
Java コレクション クラスの最も基本的なインターフェイスは次のとおりです。
コレクション: オブジェクトのセットを表し、それぞれがその子要素です。
セット: 重複する要素を含まないコレクション。
リスト: 繰り返し要素を含むことができる順次コレクション。
マップ: キー (キー) を値 (値) にマップでき、キーを繰り返すことができないオブジェクト
12. HashSet と TreeSet の違いは何ですか?
HashSet はハッシュ テーブルを使用して実装されます.要素は順不同であり、配置されたコンテンツは繰り返すことができません.null は一度だけ配置できます.
TreeSet は二分木構造で実装されており、その中の要素は順序付けられており、null を配置することはできません
13. HashSet の基本的な実装は何ですか?
HashSet の実装は HashMap に依存し、hashSet のコンストラクターは hashMap オブジェクトを初期化します。HashSet は値の重複を許可しないため、HashSet の値は HashMap のキーとして HashMap に格納され、格納された値が既に存在する場合は false を返します。
14. LinkedHashMap の実装原理は?
LinkedHashMap も HashMap に基づいて実装されます. 違いは、エントリ ヘッダーを定義することです. このヘッダーはテーブルに配置されませんが、さらに独立しています. LinkedHashMap は hashMap のエントリを継承し、前、後、およびヘッダーの 2 つの属性エントリを追加します二重連結リストを形成して、挿入順またはアクセス順によるソートを実現します。
LinkedHashMap は、boolean 変数であるソート モード accessOrder を定義します。アクセス順序の場合は true、挿入順序の場合は false です。一般に、並べ替えモードを指定する必要はなく、反復順序はデフォルトで挿入順序です。
15. コレクション クラスが Cloneable および Serializable インターフェイスを実装しないのはなぜですか
クローニングまたはシリアライゼーションのセマンティクスと意味は実装固有です。
したがって、コレクション クラスの特定の実装によって、クローンまたはシリアル化の方法を決定する必要があります。
16. イテレータとは
Iterator インターフェイスは、コレクション要素を反復処理するための多くのメソッドを提供します。すべてのコレクション クラスには、反復子インスタンスを返すメソッドが含まれています。反復子は、反復プロセス中に基になるコレクションの要素を削除できますが、コレクションの remove() メソッドを直接呼び出すことはできず、反復子の remove() メソッドを介して削除できます。
17. Iterator と ListIterator の違いは何ですか
Iterator は Set および List コレクションのトラバースに使用できますが、ListIterator は List のトラバースにのみ使用できます。
Iterator はコレクションを順方向にのみトラバースでき、ListIterator は順方向と逆方向の両方にトラバースできます。
ListIterator は Iterator インターフェイスを実装し、要素の追加、要素の置換
、前後の要素のインデックスの取得などの他の関数を含みます。
18. 配列 (Array) とリスト (ArrayList) の違いは何ですか? ArrayList の代わりに Array を使用する必要があるのはいつですか?
配列には基本型とオブジェクト型を含めることができます。ArrayList にはオブジェクト型のみを含めることができます。配列のサイズは固定されています。ArrayList は動的です。
固定サイズのプリミティブ データ型を扱う場合、ArrayList は遅くなります。
19. Java コレクション クラス フレームワークのベスト プラクティスは何ですか?
要素のサイズが固定されており、事前にわかっている場合は、ArrayList の代わりに Array を使用する必要があります。
一部のコレクション クラスでは、初期容量を指定できます。したがって、格納要素数を見積もることができれば、初期容量を設定して、ハッシュ値の再計算や容量の拡張を回避できます。
型の安全性、読みやすさ、および堅牢性の理由から、常にジェネリックを使用します。同時に、ジェネリックを使用すると、実行時に ClassCastException を回避することもできます。
Map のキーとして JDK が提供する不変クラスを使用すると、独自のクラスに hashCode() および equals() メソッドを実装することを回避できます。
プログラミングでは、実装よりもインターフェイスが優先されます。
基になるコレクションが実際に空の場合、長さ 0 のコレクションまたは配列を返し、null を返さない
20. Comparable および Comparator インターフェイスとは何ですか? それらの違いをリストする
Comparable インターフェイスは、2 つのオブジェクトを並べ替えることができる 1 つのメソッド compareTo() のみを提供します. 具体的には、入力オブジェクトが既存のオブジェクトより小さい、等しい、または大きいことを示すために、負の数、0、および正の数を返します。Comparator は compare() および equals() メソッドを提供します。前者は 2 つの入力パラメーターをソートするために使用され、負の数、0 を返し、正の数はより小さい、等しい、より大きいを表します。equals() メソッドには、入力パラメーターがコンパレーターと等しいかどうかを判断するために使用されるパラメーターとしてオブジェクトが必要です。このメソッドは、入力パラメーターもコンパレーターであり、入力パラメーターと現在のコンパレーターのソート結果が同じである場合にのみ true を返します。
21. コレクションとコレクションの違い
collection は collection クラスの上位インターフェースであり、そこから継承されるインターフェースは主に set と list です。
コレクション クラスは、コレクション クラスのヘルパー クラスであり、さまざまなコレクションに対する
検索、並べ替え、スレッド セーフ、およびその他の操作のための一連の静的メソッドを提供します。