Unity Dictionary の基礎となる実装といくつかのメソッドの基礎となる実装

目次

最下層

方法

辞書のメリットとデメリット

最下層

Unity では、Dictionary (辞書) の基本的な実装はハッシュ テーブル (ハッシュ テーブル) を使用することです。ハッシュ テーブルは、キー (キー) を対応する値 (値) にマッピングすることで高速な検索と挿入操作を実行する、一般的に使用されるデータ構造です。

ディクショナリは内部で配列を使用して要素を格納し、各要素にはキーと値のペアが含まれます。具体的には、ハッシュ関数を使用してキーをインデックス値に変換し、そのインデックス値を配列の添字として使用して、対応するキーと値のペアを格納します。

キーと値のペアを追加すると、Dictionary はまずキーのハッシュ コード (ハッシュ コード) を計算し、次にハッシュ コードに従って対応するインデックス位置を見つけます。他のキーと値のペアがその場所にすでに存在する場合、衝突が発生する可能性があります。つまり、複数のキーが同じハッシュ コードを持っています。この場合、Dictionary はリンク リストを使用して競合を解決します。つまり、リンク リストは同じインデックスの場所に保存され、そこには同じハッシュ コードで値が異なる複数のキーと値のペアが含まれます。

検索時、Dictionary は検索対象のキーのハッシュ コードに従って対応するインデックス位置を特定し、リンク リストを走査してキーの値を比較し、一致するキーと値のペアを見つけます。

効率的なパフォーマンスを維持するために、Dictionary は配列のサイズを内部で自動的に調整し、キーと値のペアを収容する適切な容量を確保することに注意してください。したがって、多数のキーと値のペアを追加すると、内部配列の再割り当てとコピー操作が発生する可能性があります。

要約すると、Dictionary の基礎となる実装には次の点が含まれます。

  • ハッシュ関数: 内部配列内のインデックス位置にキーをマップするために使用されます。Unity はいくつかの効率的なハッシュ関数アルゴリズムを使用して、ハッシュ値が均等に分散されるようにし、衝突の可能性を減らします。
  • 競合解決方法: 複数のキーが同じインデックス位置にマッピングされている場合、Unity はリンク リストや赤黒ツリーなどのデータ構造を使用して、同じインデックスを持つキーと値のペアを保存します。これにより、競合が少なくなり、パフォーマンスが向上します。
  • 動的なサイズ変更: リストと同様に、辞書にも自動的に拡張する機能があります。Dictionary の負荷係数がしきい値を超えると、より大きな内部配列が再割り当てされ、古いキーと値のペアが新しい場所に再ハッシュされます。負荷係数は、ディクショナリに格納されている要素の数と内部配列のサイズの比率です。
  • 高速ルックアップ: ディクショナリでは、ハッシュ テーブルを使用する利点により、ルックアップおよび挿入操作が高速になります。平均すると、検索操作と挿入操作の時間計算量は O(1) です。

方法

Unity では、Dictionary タイプは、キーと値のペアを操作および管理するための一連のメソッドを提供します。以下は、一般的に使用されるいくつかの Dictionary メソッドの詳細な説明です。

  1. Add(key, value): このメソッドは、最初にキーのハッシュ コードを使用して、ハッシュ関数を通じてインデックス位置を計算します。次に、このインデックスに従って、内部配列内の対応するバケットを見つけます。バケットが空の場合は、キーと値のペアがバケットに追加されます。バケットが空でない場合は、競合を処理する必要があります。競合に対処する場合、Dictionary はリンク リストを使用して、同じハッシュ コードを持つキーと値のペアを維持します。リンク リストを調べ、キーの値を比較し、一致するキーと値のペアを見つけるか、新しいキーと値のペアをリンク リストの末尾に追加します。

  2. Remove(key): このメソッドは、最初にキーのハッシュ コードを使用して、ハッシュ関数を通じてインデックスの位置を計算します。次に、インデックス位置でリンク リストを走査し、一致するキーと値のペアを見つけて、リンク リストから削除します。

  3. TryGetValue(key, out value): このメソッドは、最初にキーのハッシュ コードを使用して、ハッシュ関数を通じてインデックス位置を計算します。次に、リンクされたリストのインデックス位置を走査し、キーの値を比較し、一致するキーと値のペアを見つけて、対応する値を指定された変数に格納します。

  4. ContainsKey(key): このメソッドは、まずキーのハッシュ コードを使用して、ハッシュ関数を通じてインデックス位置を計算します。次に、インデックス位置でリンク リストを走査し、キーの値を比較し、一致するキーと値のペアを見つけます。

  5. ContainsValue(value): このメソッドは、すべてのバケットとリンク リストを走査することによって、指定された値を持つキーと値のペアを見つけます。

  6. Clear(): このメソッドは内部配列を空に初期化し、すべてのキーと値のペアを直接クリアします。

  7. Keys: このメソッドは、辞書内のすべてのキーを含むコレクションを返します。このコレクションは実際には基礎となる配列の上に構築され、すべてのバケットとリンクされたリストを反復処理してキーを収集します。返される結果の型は ですDictionary<TKey, TValue>.KeyCollection

  8. 値: このメソッドは、辞書内のすべての値を含むコレクションを返します。このコレクションは実際には基礎となる配列の上に構築され、すべてのバケットとリンクされたリストを走査して値を収集します。返される結果の型は ですDictionary<TKey, TValue>.ValueCollection

  9. Count: このメソッドは、辞書内のキーと値のペアの数を返します。基礎となる実装では、すべてのバケットとリンク リストを走査し、各リンク リスト内のノードの数を累積することによって計算されます。

  10. ryAdd(key, value): このメソッドは、キーと値のペアを辞書に追加しようとします。まずハッシュ関数を使用してキーのハッシュ コードを計算し、インデックスを通じて対応するバケットを見つけます。バケットが空の場合、キーと値のペアはバケットに直接追加されます。バケットが空でない場合は、リンクされたリストを走査して、同じキーが存在するかどうかを確認する必要があります。同じキーが存在する場合は、追加が失敗したことを示す false を返します。同じキーが存在しない場合は、キーと値のペアをリンク リストの末尾に追加し、追加が成功したことを示す場合は true を返します。

  11. GetValueOrDefault(key,defaultValue): このメソッドは、まずハッシュ関数を使用してキーのハッシュ コードを計算し、インデックスを通じて対応するバケットを見つけます。次に、リンクされたリストのインデックス位置を走査し、キーの値を比較し、一致するキーと値のペアを見つけて、その値を返します。一致するキーと値のペアが見つからない場合は、指定されたデフォルト値を返します。

  12. Remove(key, out value): このメソッドは、まずハッシュ関数を使用してキーのハッシュ コードを計算し、インデックスを通じて対応するバケットを見つけます。次に、インデックス位置でリンク リストを走査し、キーの値を比較し、一致するキーと値のペアを見つけて、リンク リストから削除します。同時に、削除された値を指定された変数に格納し、削除が成功したことを示す場合は true を返します。一致するキーと値のペアが見つからない場合は、false を返します。

  13. CopyTo(array, arrayIndex): このメソッドは、ディクショナリ内のキーと値のペアを 2 次元配列内の指定されたインデックスにコピーするために使用されます。すべてのバケットとリンク リストを走査してキーと値のペアを収集し、それらを指定された配列の位置にコピーします。

  14. TrimExcess(): このメソッドは、実際の要素数に合わせて辞書の内部配列のサイズを調整するために使用されます。多数の要素を追加または削除すると、内部配列の空き領域が多すぎる場合がありますが、この方法では実際の要素数に応じて縮小してメモリ使用量を削減できます。

  15. GetOrAdd(key, valueFactory): このメソッドは、まずハッシュ関数を使用してキーのハッシュ コードを計算し、インデックスを通じて対応するバケットを見つけます。次に、リンクされたリストのインデックス位置を走査し、キーの値を比較し、一致するキーと値のペアを見つけて、その値を返します。一致するキーと値のペアが見つからない場合は、提供されたデリゲート関数を使用して新しい値が作成され、その新しいキーと値のペアがリンク リストの末尾に追加され、新しく作成された値が返されます。

  16. GetEnumerator(): このメソッドは、ディクショナリ内のキーと値のペアをループするための列挙子 (Enumerator) を返します。列挙子はすべてのバケットとリンクされたリストを順番に走査し、キーと値のペア (KeyValuePair) を含む構造を返します。

辞書のメリットとデメリット

Unity の Dictionary タイプには次のような利点と欠点があります。

アドバンテージ:

  1. 効率的な検索操作: ディクショナリはハッシュ テーブルを使用して実装されており、一定の時間計算量 (O(1)) で検索操作を実行でき、多数の要素がある場合でも検索速度は非常に高速です。

  2. 柔軟なストレージ容量: ディクショナリはさまざまなタイプのキーと値のペアを保存できるため、データを動的に追加および管理する必要がある状況に非常に適しています。要素の追加や削除に合わせて、必要に応じて自動的にサイズ変更できます。

  3. 便利なキーと値のペアの操作: Dictionary が提供するメソッドを使用して、キーと値のペアを簡単に追加、削除、取得、確認できます。これにより、辞書内のデータの追加、削除、変更、クエリが簡単に行え、辞書内のキーと値を柔軟に処理できるようになります。

  4. ジェネリックスのサポート: Dictionary は、必要に応じてキーと値のタイプを指定できるジェネリック クラスで、タイプ セーフとコードの可読性を向上させます。

欠点:

  1. 大量のメモリ消費: ハッシュ テーブルを使用するため、Dictionary はメモリ内の一定量のスペースを占有します。特に、辞書に多数の要素が含まれている場合、または多数のハッシュ衝突がある場合、追加のメモリ消費が発生する可能性があります。

  2. 順序が維持されない: Dictionary 内のキーと値のペアは順不同で格納されます。つまり、要素の追加および走査の順序は、挿入の順序と必ずしも同じではありません。特定の順序でキーと値のペアにアクセスする必要がある場合は、他のデータ構造を使用する必要がある場合があります。

  3. ハッシュの競合の影響: 複数のキーが同じハッシュ コードを持つ場合、ハッシュの競合が発生し、検索効率が低下します。Dictionary はリンク リストを使用して競合を解決しますが、多数の競合が存在するとリンク リストが長くなり、検索および削除操作のパフォーマンスに影響を与える可能性があります。

  4. 順序付けされたニーズには適していません: キーの順序で並べ替えたり、範囲でクエリを実行したりする必要がある場合、辞書は最適な選択ではありません。この場合、SortedDictionary または並べ替えられた操作をサポートするその他のデータ構造の使用を検討する必要があります。

要約すると、Unity の Dictionary 型の最下層はハッシュ テーブルを使用して実装されており、キーのハッシュ コードを計算することで、キーと値のペアが配列インデックスにマッピングされ、効率的な検索と挿入操作が実現されます。その基盤となる実装では、ハッシュの衝突を考慮し、リンクされたリストを使用して衝突を解決し、効率的なパフォーマンスと柔軟なストレージ機能を確保します。

おすすめ

転載: blog.csdn.net/qq_66312646/article/details/132087863