一般的なインタビューの質問のコレクション

一般的なコレクションは何ですか?

A:MapインタフェースおよびCollectionインタフェースは、すべてのコレクションフレームワークの親インタフェースです。

  • Collection含むインターフェイスサブインターフェイス:ListインターフェイスとSetインターフェイス。
    • Listインタフェースの実装クラスはArrayList、次のとおりです。LinkedList、、StackおよびVector等。
    • Setインタフェースの実装クラスはHashSet、次のとおりですTreeSetLinkedHashSetなどが挙げられます。
  • Mapインタフェースの実装クラスHashMapです:TreeMapHashtable、、ConcurrentHashMapおよびProperties等。

HashMapそして、Hashtableの違いは?

  1. HashMap同期の検討に失敗するとスレッドセーフではなくなり、キーワードHashtableを使用synchronizedするとスレッドセーフになります。

  2. HashMap許可K/Vされnull、後者はK/Vに許可されていませんnull

  3. HashMapAbstractMapクラスから継承し、クラスからHashtable継承しDictionaryます。

HashMaphashCode()処理されたハッシュ値をtable添え字として直接使用しないのはなぜですか?

回答:このhashCode()メソッドは、整数型を返します。これには、-(2^31)~(2^31 - 1)約40億のマッピング空間の範囲があります。HashMap容量範囲内である16(初期デフォルト)~2^30、HashMapのは通常あまり取られた最大値よりも、デバイスはまたせることにより、あまり記憶空間を提供することは困難であるhashCode()配列のサイズ範囲の計算されたハッシュ値ではないかもしれません内、したがって、保管場所と一致することはできません。

インタビュアー:それを解決するには?

回答:HashMap独自のhash()方法を実装しました。2つの妨害により、独自のハッシュ値を高くまたは低くしてXOR演算を単独で実行し、ハッシュの衝突の確率を減らし、データ分布をより均等にします。

配列の長さが2の累乗であることが保証されてhash()いる場合は、演算および演算(&)(数组长度 - 1)の後に値を使用して、格納用の配列添え字を取得します。

  1. まず、残りの操作を行うよりも効率的です。
  2. 2番目の理由は、配列の長さが2の累乗である場合にh&(length-1)のみ同等であることですh%length
  3. 「ハッシュ値が配列のサイズと一致しない」問題を解決するための3つ。

インタビュアー:配列の長さが2の累乗であることが保証されているのはなぜですか?

A:配列の長さが2のべき乗である場合にのみ、h&(length - 1)それに相当するh%lengthことが達成key位置決め、2のべき乗も衝突の数を低減し、改善することができるHashMapクエリの効率を。

場合はlength2の累乗をれるlength - 1ことがある必要があり、バイナリに変換する11111……、請求項形式でhバイナリ作業効率が非常に高速であり、スペースが無駄にされていない;もしlength電力が2ないが、例えばlength15であり、length - 1バイナリシステムに対応する、14 1110、ことをh操作、最後のものであり0、そして0001001101011001101101111101この位置は、いくつかの要素、及びかなりの無駄なスペース、または悪化に格納されることはありません、このような場合は、アレイの位置は、配列よりも使用することができます長さがはるかに短いため、衝突の可能性がさらに高くなり、クエリの効率が低下します。これはスペースの無駄を引き起こします。

インタビュアー:なぜ2つの妨害があるのですか?

回答:これは、ハッシュ値の低次のランダム性を高め、分布がより均一になるようにすること&で、対応する配列ストレージインデックス位置のランダム性の均一性を向上させ、最終的にHash競合を減らします。2回で十分です。操作の目的。

HashMapJDK 1.7してJDK 1.8いる別のでありますか?

違う JDK 1.7 JDK 1.8
ストレージ構造 配列+リンクリスト 配列+リンクリスト+赤黒木
初期化メソッド 別の機能:inflateTable() 拡張機能に直接統合resize()
ハッシュ値の計算方法 外乱処理= 9外乱= 4ビット演算+ 5 XOR演算 外乱処理= 2外乱= 1ビット演算+ 1 XOR演算
データを保存するためのルール 競合がない場合は配列を保存し、競合する場合はリンクリストを保存します 競合がない場合は、配列を保存します;競合とリンクリストの長さ<8:単一のリンクリストを保存;競合とリンクリストの長さ> 8:ツリーと赤黒ツリーを保存
データを挿入する ヘッド補間法(最初に最後に移動したデータの元の位置について話し、次にその位置にデータを挿入する) 尾の挿入方法(リンクリストの尾への直接挿入/赤黒ツリー)
容量拡張後の保管場所の計算方法 すべての計算は元の方法(つまりhashCode->>摂動関数->> (h&length-1)に従って実行されます。 容量拡張後の法則に従って計算します(つまり、容量拡張後の場所=元の場所または元の場所+古い容量)

なぜHashMapミドルパッケージStringIntegerそのようなパッケージは次のように適しているのKですか?

A: StringInteger包装缶保証の他の特性がHash変化し、精度の値を計算することができない、効果的に減らすことができHash、衝突の可能性を。

  • それらはすべてfinal不変で保証された不変性であり、key取得したhash値が異なる場合はありません
  • 内部メソッドが書き直されたequals()hashCode()などHashMap内部仕様に従っている(上記のputValueプロセスを確認できない)ため、Hash値の計算エラーが発生しにくい

インタビュアー:私は自分の作りたい場合はどうObjectとしてKどのように私はそれを行う必要がありますか?

回答:書き換えhashCode()equals()方法。

  • 書き換えhashCode()は、格納されたデータの格納場所を計算する必要があるためです。パフォーマンスを向上させるために、オブジェクトのキー部分をハッシュコードの計算から除外しないように注意してくださいHash

  • 書き換えequals()メソッドは、反射性、対称性、推移性、一貫性、および非null参照値に準拠する必要がありますx。これらx.equals(null)は返される必要があります。false目的はkey、ハッシュテーブル内の一意性を確保することです。

Javaコレクションの高速障害メカニズム " fail-fast"?

A:ときに、エラー検出メカニズムは、Javaの集合である構造変化のセットで複数のスレッド動作中には、原因に思われるfail-fastメカニズム。

例:2つのスレッド(スレッド1、スレッド2)があり、スレッド1 IteratorがコレクションAの要素をトラバースし、ある時点でスレッド2がコレクションAの構造を変更したとします(構造的な変更であり、単純な変更ではありません)。コンテンツ要素のコレクション)、そのプログラムがスローされます。この時ConcurrentModificationException生成、例外をfail-fastメカニズムを。

理由:トラバースとプロセスの使用トラバースするときイテレータが直接コレクションの内容にアクセスするmodCount変数を。コンテンツは、コレクションを横断する時に変更を生じた場合、それが変更されますmodCount値を。使用イテレータたびにhashNext()/next()検出するトラバース要素の前に次のmodCount変数があるかどうかをexpectedmodCount次にトラバースに返される値が、そうでない場合は例外をスローし、トラバースを終了します。

解決策:

  1. 横断プロセスでは、すべての変更に関連するmodCountすべて一緒にやりがいのある場所synchronized

  2. 使用CopyOnWriteArrayList交換しますArrayList

ArrayListそして、Vectorの違いは?

A:2つのクラスが実装するListインターフェース(Listインターフェース継承Collectionインタフェース)、それらはセットを注文され、その要素の位置は、これらの二つのセットに格納され、ダイナミックアレイの等価連続している、我々はインデックス位置は、要素によって除去することができた後に、データをある反復に許容されるHashSet最大の差とセットのようなHashSetコレクションまたはその中の要素を取得するために、インデックス番号によって識別することができないなど、許可されていないが繰り返し要素があります。

ArrayListそして、Vector2つの側面の違い:

  1. 同期はVectorそのスレッド同期方法(プラスの間である、スレッドセーフであるsynchronizedキー)、及びArrayList方法は、スレッド同期である間、スレッドセーフです。コレクションにアクセスするスレッドが1つだけの場合はArrayList、スレッドの安全性の問題を考慮しないため、を使用するのが最適です。効率が高くなります。複数のスレッドがコレクションにアクセスする場合はVectorを使用するのが最適です。スレッドセーフなコードを考えて、自分で作成してください。

  2. データ成長:ArrayListVector内部に記憶その要素数が容量ニーズが増加超える場合、初期容量の大きさを有するArrayListVector、1個のメモリセルが増加しないだけを増加させるため、記憶領域を各メモリ空間を、代わりに、複数のストレージユニットが追加され、毎回追加されるストレージユニットの数は、メモリ空間の使用率とプログラムの効率の間の一定のバランスです。Vectorデータ満杯である(負荷因子1)成長(増分拡張:2倍の体積)を倍増し、ArrayListデータ量を元の体積(0.5倍+の容量(負荷率0.5)成長の半分に達したとき1)スペース。

ArrayListそして、LinkedListの違いは?

A:LinkedList実装ListDequeインターフェイス、一般に二重にリンクされたリストと呼ばれる、ArrayList実装Listインタフェース、ダイナミックアレイ。

  1. LinkedListより高い効率を挿入し、データを削除ArrayListするための検索でindexデータの高効率。
  2. LinkedList比率は、ArrayListより多くのメモリを必要とします。

Arrayそして、ArrayListの違いは何ですか?ときにする必要ArrayはないArrayListのですか?

回答:違いは次のとおりです。

  1. Array基本タイプとオブジェクトタイプを含めることができますArrayList。オブジェクトタイプのみを含めることができます
  2. Arrayサイズは固定されておりArrayList、サイズは動的に変化します。
  3. ArrayListオファーなど多くのメソッドやプロパティ、 addAll()など:removeAll()、、iterator()というように。

基本タイプのデータの場合、コレクションは自動ビニングを使用してコーディングの作業負荷を軽減します。ただし、この方法は、固定サイズの基本的なデータ型を扱う場合は比較的低速です。

HashSetデータが再現可能でないことを確認するにはどうすればよいですか?

A:HashSet最下層は実際HashMapはです。インターフェイスHashSet実装しSet、データをKとして使用しただけでV値は同じダミー値で保存されていますソースコードを見ることができます:

public boolean add(E e) {
	// 调用HashMap的put方法,PRESENT是一个至始至终都相同的虚值
    return map.put(e, PRESENT)==null;
}

値自体を繰り返すことは許可されていないためHashMapK値がHashMap途中K/Vで同じ場合、V古いものが新しい上書きさV、古いものが返されVます。次に、HashSetこの文を実行すると常に1が返されfalse、挿入が失敗し、保証されますデータの非再現性。

公開された94元の記事 ウォンの賞賛0 ビュー722

おすすめ

転載: blog.csdn.net/qq_46578181/article/details/105411856