一般的なコレクションは何ですか?
A:Map
インタフェースおよびCollection
インタフェースは、すべてのコレクションフレームワークの親インタフェースです。
Collection
含むインターフェイスサブインターフェイス:List
インターフェイスとSet
インターフェイス。List
インタフェースの実装クラスはArrayList
、次のとおりです。LinkedList
、、Stack
およびVector
等。Set
インタフェースの実装クラスはHashSet
、次のとおりですTreeSet
、LinkedHashSet
などが挙げられます。
Map
インタフェースの実装クラスHashMap
です:TreeMap
、Hashtable
、、ConcurrentHashMap
およびProperties
等。
HashMap
そして、Hashtable
の違いは?
-
HashMap
同期の検討に失敗するとスレッドセーフではなくなり、キーワードHashtable
を使用synchronized
するとスレッドセーフになります。 -
HashMap
許可K/V
されnull
、後者はK/V
に許可されていませんnull
。 -
HashMap
AbstractMap
クラスから継承し、クラスからHashtable
継承しDictionary
ます。
HashMap
hashCode()
処理されたハッシュ値をtable
添え字として直接使用しないのはなぜですか?
回答:このhashCode()
メソッドは、整数型を返します。これには、-(2^31)~(2^31 - 1)
約40億のマッピング空間の範囲があります。HashMap
容量範囲内である16
(初期デフォルト)~2^30
、HashMapのは通常あまり取られた最大値よりも、デバイスはまたせることにより、あまり記憶空間を提供することは困難であるhashCode()
配列のサイズ範囲の計算されたハッシュ値ではないかもしれません内、したがって、保管場所と一致することはできません。
インタビュアー:それを解決するには?
回答:HashMap
独自のhash()
方法を実装しました。2つの妨害により、独自のハッシュ値を高くまたは低くしてXOR演算を単独で実行し、ハッシュの衝突の確率を減らし、データ分布をより均等にします。
配列の長さが2の累乗であることが保証されてhash()
いる場合は、演算および演算(&
)(数组长度 - 1
)の後に値を使用して、格納用の配列添え字を取得します。
- まず、残りの操作を行うよりも効率的です。
- 2番目の理由は、配列の長さが2の累乗である場合に
h&(length-1)
のみ同等であることですh%length
。 - 「ハッシュ値が配列のサイズと一致しない」問題を解決するための3つ。
インタビュアー:配列の長さが2の累乗であることが保証されているのはなぜですか?
A:配列の長さが2のべき乗である場合にのみ、h&(length - 1)
それに相当するh%length
ことが達成key
位置決め、2のべき乗も衝突の数を低減し、改善することができるHashMap
クエリの効率を。
場合はlength
2の累乗をれるlength - 1
ことがある必要があり、バイナリに変換する11111……
、請求項形式でh
バイナリ作業効率が非常に高速であり、スペースが無駄にされていない;もしlength
電力が2ないが、例えばlength
15であり、length - 1
バイナリシステムに対応する、14 1110
、ことをh
操作、最後のものであり0
、そして0001
、0011
、0101
、1001
、1011
、0111
、1101
この位置は、いくつかの要素、及びかなりの無駄なスペース、または悪化に格納されることはありません、このような場合は、アレイの位置は、配列よりも使用することができます長さがはるかに短いため、衝突の可能性がさらに高くなり、クエリの効率が低下します。これはスペースの無駄を引き起こします。
インタビュアー:なぜ2つの妨害があるのですか?
回答:これは、ハッシュ値の低次のランダム性を高め、分布がより均一になるようにすること&
で、対応する配列ストレージインデックス位置のランダム性の均一性を向上させ、最終的にHash
競合を減らします。2回で十分です。操作の目的。
HashMap
JDK 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
ミドルパッケージString
とInteger
そのようなパッケージは次のように適しているのK
ですか?
A: String
、Integer
包装缶保証の他の特性が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
次にトラバースに返される値が、そうでない場合は例外をスローし、トラバースを終了します。
解決策:
-
横断プロセスでは、すべての変更に関連する
modCount
すべて一緒にやりがいのある場所synchronized
。 -
使用
CopyOnWriteArrayList
交換しますArrayList
。
ArrayList
そして、Vector
の違いは?
A:2つのクラスが実装するList
インターフェース(List
インターフェース継承Collection
インタフェース)、それらはセットを注文され、その要素の位置は、これらの二つのセットに格納され、ダイナミックアレイの等価連続している、我々はインデックス位置は、要素によって除去することができた後に、データをある反復に許容されるHashSet
最大の差とセットのようなHashSet
コレクションまたはその中の要素を取得するために、インデックス番号によって識別することができないなど、許可されていないが繰り返し要素があります。
ArrayList
そして、Vector
2つの側面の違い:
-
同期は:
Vector
そのスレッド同期方法(プラスの間である、スレッドセーフであるsynchronized
キー)、及びArrayList
方法は、スレッド同期である間、スレッドセーフです。コレクションにアクセスするスレッドが1つだけの場合はArrayList
、スレッドの安全性の問題を考慮しないため、を使用するのが最適です。効率が高くなります。複数のスレッドがコレクションにアクセスする場合はVector
、を使用するのが最適です。スレッドセーフなコードを考えて、自分で作成してください。 -
データ成長:
ArrayList
とVector
内部に記憶その要素数が容量ニーズが増加超える場合、初期容量の大きさを有するArrayList
とVector
、1個のメモリセルが増加しないだけを増加させるため、記憶領域を各メモリ空間を、代わりに、複数のストレージユニットが追加され、毎回追加されるストレージユニットの数は、メモリ空間の使用率とプログラムの効率の間の一定のバランスです。Vector
データ満杯である(負荷因子1)成長(増分拡張:2倍の体積)を倍増し、ArrayList
データ量を元の体積(0.5倍+の容量(負荷率0.5)成長の半分に達したとき1)スペース。
ArrayList
そして、LinkedList
の違いは?
A:LinkedList
実装List
とDeque
インターフェイス、一般に二重にリンクされたリストと呼ばれる、ArrayList
実装List
インタフェース、ダイナミックアレイ。
LinkedList
より高い効率を挿入し、データを削除ArrayList
するための検索でindex
データの高効率。LinkedList
比率は、ArrayList
より多くのメモリを必要とします。
Array
そして、ArrayList
の違いは何ですか?ときにする必要Array
はないArrayList
のですか?
回答:違いは次のとおりです。
Array
基本タイプとオブジェクトタイプを含めることができますArrayList
。オブジェクトタイプのみを含めることができます。Array
サイズは固定されておりArrayList
、サイズは動的に変化します。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;
}
値自体を繰り返すことは許可されていないためHashMap
、K
値がHashMap
途中K/V
で同じ場合、V
古いものが新しい値で上書きされV
、古いものが返されV
ます。次に、HashSet
この文を実行すると常に1が返されfalse
、挿入が失敗し、保証されますデータの非再現性。