JDK1.8.0_144アドレスをダウンロード://www.vevb.com/softs/551512.html
AbstractMap Abstractクラスは、いくつかのシンプルで一般的な方法を実装していますが、それ自体が難しくありません。しかし、この抽象クラスには、注意を払う価値がある2つの方法があります。 Keyset and Valuesメソッドソースコードの実装は、教科書スタイルのモデルと言えます。
抽象クラスは通常、それぞれのサブクラスに共通の方法を実装するためのスケルトンとして実装されます。前の記事では、MAPインターフェイスについて説明し、この記事ではAbstractMap Abstractクラスを分析および調査します。
Javaには、マップタイプのデータ構造がかなりあります。 AbstractMapは、スケルトンの実装として、マップインターフェイスのいくつかの方法を実装しています。つまり、サブクラスにパブリックメソッドを提供し、実装のないさまざまなマップが異なる場合があります。
抽象クラスでは、新しいキーワードを介して抽象クラスのインスタンスを直接作成することはできませんが、コンストラクターを持つことができます。 AbstractMapは、保護された修正されたパラメーターレスコンストラクターを提供します。つまり、サブクラスのみがアクセスできることを意味します(もちろん、抽象クラス自体であり、他のクラスを直接インスタンス化することはできません)。つまり、サブクラスのみがこのパラメーターレスコンストラクターを呼び出すことができます。
エントリインターフェイスは、マップインターフェイスで内部的に定義されます。このインターフェイスは、キー値のキー値ペアを維持するためのマップマップの内部実装であり、キー値はこのマップに保存されます。 AbstractMapはこの内部インターフェイスを実装します。合計2つあります。1つは可変simpleEnterryであり、もう1つは不変のsimpleimmutable -entryです。
public static class simpleEntry <k、v>はエントリ<k、v>、java.io.serializableを実装します
map.entry <k、v>インターフェイスが実装され、シリアル化可能(シリアル化できます)。
その方法は比較的単純であり、そのすべては価値を取得して値を保存する操作です。キー値の定義は最終的な変更です。つまり、不変の参照です。さらに、そのsetValueメソッドはわずかに特別です。保存された値は保存された値ではありませんが、古い値は返されます。あなたが学ぶ必要があるのは、それが書き直す等しいハッシュコード方法です。
public boolean等しい(オブジェクトo){if(!(o instanceof map.entry))// map.entry <?、?、> e =(map.entry <?、?>)o; //オブジェクトタイプをmap.entryタイプに強制する、パラメーターは「?」を使用します。 「k、v」の代わりに、ジェネリックのタイプが実行時に消去されるためです。コンパイラは、タイプkとvとは何かを知りません。 //キーと値はそれぞれ判断のためにEQメソッドを呼び出し、両方が両方が戻ると等しい。 } private static boolean eq(オブジェクトO1、オブジェクトO2){return o1 == null? o2 == null:o1.equals(o2); //この3項目の演算子も非常に単純ですが、O1とO2はここではオブジェクトタイプですが、オブジェクトタイプの等しい方法は「==」で参照されるため、実際にはO1タイプは文字列になる可能性があると考えないでください。 }Equalsメソッドを正しく書き換えて正しく使用するには、通常、ハッシュコードメソッドを書き換える必要があります。
public int hashcode(){return(key == null?0:key.hashcode()) ^(value == null?0:value.hashcode()); //キーと値の値がnullでない場合、ハッシュコードはXoredになります。 }public static class simpleimmutableentry <k、v>はエントリ<k、v>、java.io.serializable simpleimmutableentryを実装します
Immutableと定義されているエントリは、SetValueメソッドを提供しないため、実際には不変であり、複数のスレッドに同時にアクセスされる場合、自然にSetValueメソッドを介して変更できないためです。 SimpleEntryと比較して、その重要なメンバー変数は最終型として定義されます。 SetValueメソッドを呼び出すと、SupportedoperationExceptionの例外がスローされます。
その等しいとハッシュコードメソッドは、SimpleEntryと一致しています。
次に、AbstractMap Abstractクラスによって実装されているマップインターフェイスのどのメソッドを確認します。
public int size()
エントリセットメソッドはマップで定義されており、Map.Entryのセットコレクションを返します。セットコレクションのサイズ方法は、マップのサイズである直接呼び出されます。
public boolean isempty()
0に等しい上記のサイズの方法を呼び出し、空です。
public boolean containsKey(オブジェクトキー)
この方法の実装は比較的簡単です。 EntrySetメソッドを呼び出すことにより、セットコレクションのイテレーターが取得され、パラメーターキーでトラバースされます。マップは、nullのキー値として保存できます。 key = nullは特別な特別なストレージ(ハッシュコード値を計算できない)でマップに保存されるため、パラメーターキーが空であるかどうかを判断する方法も実行しました。
public boolean containsValue(オブジェクト値)
このメソッドの実装は、ContainsKeyと一致しています。
public v get(オブジェクトキー)
このメソッドの実装は上記の2つに似ています。違いは、上記がブール値に等しいことです。この方法は値を返します。
public v put(k key、v value)
キー価値のペアをマップに保存する方法は詳細に実装されておらず、サポートされていないエクセプトが直接スローされます。
public v remove(オブジェクトキー)
パラメーターキーを介してマップで指定されたキー値キー値ペアを削除します。この方法も非常に簡単です。また、Map.entryのセットコレクションをイテレーターを介して横断し、対応するキー値を見つけ、redyを削除して、iterator#removeメソッドを呼び出します。
public void putall(map <?extends k、?extends v> m)
この方法は、着信マップを通過し、PUTメソッドを呼び出して保存するだけで非常に簡単です。
public void clear()
エントリセットメソッドを呼び出してセットコレクションを取得し、セット#clear()メソッドを呼び出してクリアします。
public set <k> keyset()
マップキー値のセットコレクションを返します。 AbstractMapは、メンバー変数「Transient Set <K> Keyset」を定義します。 JDK7では、キーズセット変数は揮発性によって変更されますが、JDK8では揮発性によって変更されません。 Keyset変数に関するコメントで説明されています。これらのフィールドにアクセスする方法はそれ自体で同期されておらず、揮発性はスレッドの安全性を保証できないと説明しています。 Keysetメソッドの実装は興味深いです。
まず第一に、この方法について考えてみると、キー値のセットセットを返すことです。当然のことながら、単純な実装方法を考え、エントリアレイを通過してキー値を取り出して、次のコードと同様にセットに配置できます。
public set <k> keyset(){set <k> ks = null; for(map.entry <k、v> entry:entryset()){ks.add(entry.getKey()); } return ks;}これは、Keysetメソッドが呼び出されるたびに、エントリアレイを通過し、データボリュームが大きいと効率が大幅に低下することを意味します。 JDKソースコードは非常によく書かれており、横断の方法を採用していないと言わざるを得ません。エントリを通過しない場合、このマップが現時点でキー値のキー価値ペアを追加したことをどのようにして知っていますか?
答えは、Keysetメソッド内の新しいカスタムセットコレクションを再実装することであり、このカスタムセットコレクションではIteratorメソッドが書き直されています。これが鍵です。 IteratorメソッドはIteratorインターフェイスを返し、ここで再実装されます。 EntrySetメソッドを呼び出してから、Iteratorメソッドを呼び出します。以下は、コードと組み合わせて分析されます。
public set <k> keyset(){set <k> ks = keyset; //定義されたトランジェントセット<k> keyset if(ks == null){//最初の呼び出しは間違いなくnullです。次のコードks = new abstractset <k>(){//カスタムセットパブリックイテレーター<k> iterator(){// returator return return the set return <k> iterator <k> interator <k> interator <k> interator <k> private returator estear iterator <entry <k、v >> i = entryset()。iterator(); //セットコレクションIterator Iterator public boolean hasnext(){return i.hasnext(); //キー値の判断は、エントリの判断です} public k next(){return i.next()。getKey(); //次のキー値は、エントリ#getKey} public void remove(){i.remove();を取得することです。 //キー値を削除し、エントリを削除}}; } public int size(){//書き換えset#sizeメソッドはabstractmap.this.size()を返します; //キーの値は、マップ全体の大きさですので、このクラスのサイズメソッドを呼び出してください。これは内部クラスです。このキーワードを使用して、このクラスを直接表現します。 AbstractMapのサイズメソッドが呼び出されることを示す必要があります。これがなければ、それは静的な静的方法であることを意味します//キー値があるかどうかについては、マップが空であるかどうかを意味するため、このクラスのisemptyメソッドを呼び出すだけです} public void clear(){//書き換えセット#clear method abstractmap.this.clear(); //キー値をクリアするだけで、マップをクリアするためだけなので、このクラスの明確なメソッドを呼び出すだけです} public boolean contains(// rewrite set#contains method return abstractmap.this.containskey(k); //セットがデータkを含むかどうかを判断します。つまり、マップにキー値が含まれているかどうかを意味するため、このクラスのcontainskeyメソッドを呼び出してください}}; keyset = ks; //このカスタムセットコレクションを可変キーズセットに割り当てます。将来キーズセットメソッドを再度呼び出すとき、キーズセットはヌルではないため、直接返すだけです。 } ksを返します。これは非常に賢い実装だと思います。この方法はキー値を中心に展開しますが、エントリを横断することなく、エントリと組み合わせて実際に実装できます。同時に、上記のエントリセット#iteratorメソッドを呼び出すことは、テンプレートメソッドモードのベストプラクティスであると述べています。エントリセットはAbstractMapに実装されていないが、完了するためにそのサブクラスに任されているが、キーズセットメソッドはテンプレートメソッドパターンである「アルゴリズムスケルトン」で実装できるためです。
パブリックコレクション<v>値()
値メソッドについては、KeySetを完全に参照できます。 2つは同じ効果があるので、スペースを節約するためにここで繰り返されません。
パブリックアブストラクトセット<entry <k、v >> entryset()
抽象的なメソッドがサブクラスに引き渡されて完成し、この方法が特に「一般」ではないことを示しています。
パブリックブールの等しい(オブジェクトO)
マップは、マップ内の各キー値ペアのキーと値が1つずつ真実に戻る場合のみを規定しています。この方法では、最初に単純な条件を判断します。参照が等しい場合は、直接trueを返します。パラメーターoがマップタイプでない場合は、直接falseを返します。 2つのマップの数が異なる場合は、直接falseを返します。その場合にのみ、エントリアレイを繰り返し、エントリのキーと値が1つずつ対応するかどうかを比較します。この方法は簡単ですが、これによりインスピレーションが与えられます。条件付き判断では、まず単純な基本的なものを判断し、次に複雑なものを判断する必要があります。
public int hashcode()
オブジェクトクラスの等しい方法を書き換え、ハッシュコードの書き換えも必要です。 AbstractMapのHashCodeの実装は、すべてのMap.Entry(以下はSimpleEntryまたはSimpleImmutableEntry)のハッシュコード値を最後に追加することであり、最終的な合計はMAPのハッシュコード値として使用されます。
public string toString()
この方法については何も言うことはありません。すべてのキー価値のペアを取り出し、StringBuilderを使用してそれらをスプライスすることです。
保護されたオブジェクトclone()は、cloneNotsupportedexceptionをスローします
浅いコピーを実装します。これは、可変キーセットと値の浅いコピーであり、2つの浅いコピーによって引き起こされる問題を防ぎます。