私は.NETでジェネリックスの基礎を学んできました。しかし、私はHashtable
の一般的な等価物が表示されません。ジェネリックハッシュテーブルクラスを作成するためのサンプルC#コードをいくつかご紹介してください。Hashtableの一般的なバージョンは何ですか?
答えて
辞書ハッシュテーブルの交換で100%の低下ではないことに注意してください。
NULLを処理する方法に若干の違いがあります。 存在しないキーを参照しようとすると、ディクショナリは例外をスローします。 HashTableはnullを返します。 その理由は、値が値型である可能性があります。はをnullにできないためです。ハッシュテーブルでは、値は常にObjectであるため、nullを返すことは少なくとも可能でした。
ハッシュテーブルクラスの汎用バージョンは、System.Collections.Generic.Dictionaryクラスです。
Dictionary<int, string> numbers = new Dictionary<int, string>();
numbers.Add(1, "one");
numbers.Add(2, "two");
// Display all key/value pairs in the Dictionary.
foreach (KeyValuePair<int, string> kvp in numbers)
{
Console.WriteLine("Key: " + kvp.Key + "\tValue: " + kvp.Value);
}
MSDN lobandバージョンへのリンクを編集しました。 –
好奇心。なぜマイクロソフトは辞書をハッシュテーブルと呼び、ハッシュテーブルをハッシュテーブルと呼びますか?私がジェネリックの辞書について読むまで、ハッシュテーブルはいつも私に不思議そうでした。 – johnny
のHashtableのジェネリックバージョンはDictionary<TKey,TValue>
クラス(link)です。ここではかなり直接的な翻訳の辞書の最も直接的同等にハッシュテーブルを使用してから翻訳いくつかのサンプルコード(引数簡潔にするために削除チェックが)
public HashTable Create(int[] keys, string[] values) {
HashTable table = new HashTable();
for (int i = 0; i < keys.Length; i++) {
table[keys[i]] = values[i];
}
return table;
}
public Dictionary<object,object> Create(int[] keys, string[] values) {
Dictionary<object,object> map = Dictionary<object,object>();
for (int i = 0; i < keys.Length; i++) {
map[keys[i]] = values[i];
}
return map;
}
です。しかし問題は、これが実際にジェネリックのタイプセーフな機能を利用していないことです。第二の機能は、次のように書かれており、より多くの種類安全であると何のボクシングのオーバーヘッドさらに良い
public Dictionary<int,string> Create(int[] keys, string[] values) {
Dictionary<int,string> map = Dictionary<int,string>();
for (int i = 0; i < keys.Length; i++) {
map[keys[i]] = values[i];
}
return map;
}
をinccurすることはできませんでした。ここで、私は一般的なHashtableのラッパークラスを作成し、完全にジェネリックバージョン
public Dictionary<TKey,TValue> Create<TKey,TValue>(TKey[] keys, TValue[] values) {
Dictionary<TKey,TValue> map = Dictionary<TKey,TValue>();
for (int i = 0; i < keys.Length; i++) {
map[keys[i]] = values[i];
}
return map;
}
そして、さらに柔軟である1(おかげでジョエルは、私はこれを逃し指摘のため)です興味を持っている人のために
public Dictionary<TKey,TValue> Create<TKey,TValue>(
IEnumerable<TKey> keys,
IEnumerable<TValue> values) {
Dictionary<TKey,TValue> map = Dictionary<TKey,TValue>();
using (IEnumerater<TKey> keyEnum = keys.GetEnumerator())
using (IEnumerator<TValue> valueEnum = values.GetEnumerator()) {
while (keyEnum.MoveNext() && valueEnum.MoveNext()) {
map[keyEnum.Current] = valueEnum.Current;
}
}
return map;
}
これは型の安全性を強化するのに役立ち、ジェネリックIDictionary、ICollection、IEnumerable型として渡すことができますが、非ジェネリックなHashtableではできません。以下は実装です。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Common.Collections.Generic
{
public class Hashtable<TKey, TValue> : IDictionary<TKey, TValue>
, ICollection<KeyValuePair<TKey, TValue>>
, IEnumerable<KeyValuePair<TKey, TValue>>
, IDictionary
, ICollection
, IEnumerable
{
protected Hashtable _items;
/// <summary>
/// Initializes a new, empty instance of the Hashtable class using the default initial capacity, load factor, hash code provider, and comparer.
/// </summary>
public Hashtable()
{
_items = new Hashtable();
}
/// <summary>
/// Initializes a new, empty instance of the Hashtable class using the specified initial capacity, and the default load factor, hash code provider, and comparer.
/// </summary>
/// <param name="capacity">The approximate number of elements that the Hashtable object can initially contain. </param>
public Hashtable(int capacity)
{
_items = new Hashtable(capacity);
}
/// <summary>
/// Actual underlying hashtable object that contains the elements.
/// </summary>
public Hashtable Items { get { return _items; } }
/// <summary>
/// Adds an element with the specified key and value into the Hashtable.
/// </summary>
/// <param name="key">Key of the new element to add.</param>
/// <param name="value">Value of the new elment to add.</param>
public void Add(TKey key, TValue value)
{
_items.Add(key, value);
}
/// <summary>
/// Adds an element with the specified key and value into the Hashtable.
/// </summary>
/// <param name="item">Item containing the key and value to add.</param>
public void Add(KeyValuePair<TKey, TValue> item)
{
_items.Add(item.Key, item.Value);
}
void IDictionary.Add(object key, object value)
{
this.Add((TKey)key, (TValue)value);
}
/// <summary>
/// Add a list of key/value pairs to the hashtable.
/// </summary>
/// <param name="collection">List of key/value pairs to add to hashtable.</param>
public void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> collection)
{
foreach (var item in collection)
_items.Add(item.Key, item.Value);
}
/// <summary>
/// Determines whether the Hashtable contains a specific key.
/// </summary>
/// <param name="key">Key to locate.</param>
/// <returns>True if key is found, otherwise false.</returns>
public bool ContainsKey(TKey key)
{
return _items.ContainsKey(key);
}
/// <summary>
/// Determines whether the Hashtable contains a specific key.
/// </summary>
/// <param name="item">Item containing the key to locate.</param>
/// <returns>True if item.Key is found, otherwise false.</returns>
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return _items.ContainsKey(item.Key);
}
bool IDictionary.Contains(object key)
{
return this.ContainsKey((TKey)key);
}
/// <summary>
/// Gets an ICollection containing the keys in the Hashtable.
/// </summary>
public ICollection<TKey> Keys
{
get { return _items.ToList<TKey>(); }
}
ICollection IDictionary.Keys
{
get { return this.Keys.ToList(); }
}
/// <summary>
/// Gets the value associated with the specified key.
/// </summary>
/// <param name="key">The key of the value to get.</param>
/// <param name="value">When this method returns, contains the value associated with the specified key,
/// if the key is found; otherwise, the default value for the type of the value parameter. This parameter
/// is passed uninitialized.</param>
/// <returns>true if the hashtable contains an element with the specified key, otherwise false.</returns>
public bool TryGetValue(TKey key, out TValue value)
{
value = (TValue)_items[key];
return (value != null);
}
/// <summary>
/// Gets an ICollection containing the values in the Hashtable.
/// </summary>
public ICollection<TValue> Values
{
get { return _items.Values.ToList<TValue>(); }
}
ICollection IDictionary.Values
{
get { return this.Values.ToList(); }
}
/// <summary>
/// Gets or sets the value associated with the specified key.
/// </summary>
/// <param name="key">The key whose value to get or set. </param>
/// <returns>The value associated with the specified key. If the specified key is not found,
/// attempting to get it returns null, and attempting to set it creates a new element using the specified key.</returns>
public TValue this[TKey key]
{
get
{
return (TValue)_items[key];
}
set
{
_items[key] = value;
}
}
/// <summary>
/// Removes all elements from the Hashtable.
/// </summary>
public void Clear()
{
_items.Clear();
}
/// <summary>
/// Copies all key/value pairs in the hashtable to the specified array.
/// </summary>
/// <param name="array">Object array to store objects of type "KeyValuePair<TKey, TValue>"</param>
/// <param name="arrayIndex">Starting index to store objects into array.</param>
public void CopyTo(Array array, int arrayIndex)
{
_items.CopyTo(array, arrayIndex);
}
/// <summary>
/// Copies all key/value pairs in the hashtable to the specified array.
/// </summary>
/// <param name="array">Object array to store objects of type "KeyValuePair<TKey, TValue>"</param>
/// <param name="arrayIndex">Starting index to store objects into array.</param>
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
_items.CopyTo(array, arrayIndex);
}
/// <summary>
/// Gets the number of key/value pairs contained in the Hashtable.
/// </summary>
public int Count
{
get { return _items.Count; }
}
/// <summary>
/// Gets a value indicating whether the Hashtable has a fixed size.
/// </summary>
public bool IsFixedSize
{
get { return _items.IsFixedSize; }
}
/// <summary>
/// Gets a value indicating whether the Hashtable is read-only.
/// </summary>
public bool IsReadOnly
{
get { return _items.IsReadOnly; }
}
/// <summary>
/// Gets a value indicating whether access to the Hashtable is synchronized (thread safe).
/// </summary>
public bool IsSynchronized
{
get { return _items.IsSynchronized; }
}
/// <summary>
/// Gets an object that can be used to synchronize access to the Hashtable.
/// </summary>
public object SyncRoot
{
get { return _items.SyncRoot; }
}
/// <summary>
/// Removes the element with the specified key from the Hashtable.
/// </summary>
/// <param name="key">Key of the element to remove.</param>
public void Remove(TKey key)
{
_items.Remove(key);
}
/// <summary>
/// Removes the element with the specified key from the Hashtable.
/// </summary>
/// <param name="item">Item containing the key of the element to remove.</param>
public void Remove(KeyValuePair<TKey, TValue> item)
{
this.Remove(item.Key);
}
bool IDictionary<TKey, TValue>.Remove(TKey key)
{
var numValues = _items.Count;
_items.Remove(key);
return numValues > _items.Count;
}
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
var numValues = _items.Count;
_items.Remove(item.Key);
return numValues > _items.Count;
}
void IDictionary.Remove(object key)
{
_items.Remove(key);
}
/// <summary>
/// Returns an enumerator that iterates through the hashtable.
/// </summary>
/// <returns>An enumerator for a list of key/value pairs.</returns>
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (DictionaryEntry? item in _items)
yield return new KeyValuePair<TKey, TValue>((TKey)item.Value.Key, (TValue)item.Value.Value);
}
/// <summary>
/// Returns an enumerator that iterates through the hashtable.
/// </summary>
/// <returns>An enumerator for a list of key/value pairs as generic objects.</returns>
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
IDictionaryEnumerator IDictionary.GetEnumerator()
{
// Very old enumerator that no one uses anymore, not supported.
throw new NotImplementedException();
}
object IDictionary.this[object key]
{
get
{
return _items[(TKey)key];
}
set
{
_items[(TKey)key] = value;
}
}
}
}
私は辞書対ハッシュテーブルのいくつかのテストを行って、文字列のキーと文字列値のペアで使用した場合のHashtableが少ないメモリを使用するように思わ除い2は、ほぼ同じ実行を発見しました。
TestInitialize Dictionary_50K_Hashtable
Number objects 50000, memory usage 905164
Insert, 22 milliseconds.
A search not found, 0 milliseconds.
Search found, 0 milliseconds.
Remove, 0 milliseconds.
Search found or not found, 0 milliseconds.
TestCleanup Dictionary_50K_Hashtable
TestInitialize Dictionary_50K_Dictionary
Number objects 50000, memory usage 1508316
Insert, 16 milliseconds.
A search not found, 0 milliseconds.
Search found, 0 milliseconds.
Remove, 0 milliseconds.
Search found or not found, 0 milliseconds.
TestCleanup Dictionary_50K_Dictionary
- 1. 一般的なプログラミング言語の "鉄"バージョン
- 2. djangoのクラスベースの一般的なビューのユースケースは何ですか
- 3. パイプラインの一般的なパイプラインの危険性は何ですか?
- 4. Pythonのenumの一般的なプラクティスは何ですか?
- 5. 一般的なWebブラウザのアドレスバーの動作は何ですか?
- 6. Javascriptブックマークレットの一般的なデザインパターンは何ですか?
- 7. RAIIクラスの一般的な命名規則は何ですか?
- 8. ビットアレーの一般的な用途は何ですか?
- 9. Akka Microkernelの一般的な使用例は何ですか?
- 10. 最も一般的なCSSのプラクティスは何ですか?
- 11. apacheの一般的な設定は何ですか
- 12. 最も一般的なCSSの問題は何ですか?
- 13. Itinero + Mapsui + OsmSharpの一般的なPCLプロファイルバージョンは何ですか?
- 14. 一般的なシナリオとエンドユーザーレポートの設計は何ですか?
- 15. 一般的な3Dゲームパターンとは何ですか?
- 16. 一般的なember.jsオープンソースプロジェクトとは何ですか?
- 17. .NET/SQL Server環境でデータベースのバージョン管理を管理する一般的な方法は何ですか?
- 18. 一般的な目的として使用するMIMEタイプは何ですか?
- 19. スクリプトの一般的なGUIですか?
- 20. さまざまなkuberentesコンポーネントのシャーディングメトリックの一般的なオプションは何ですか?
- 21. djangoでの一般的なデータやプロセスのベストプラクティスは何ですか?
- 22. 春のプロジェクトでAOPの最も一般的な用途は何ですか
- 23. 一般的な/一般的なAndroid搭載端末のタッチポイント数
- 24. スパーク:一般的な「メモリ不足」エラーの一般的なベストプラクティス?
- 25. Springでスケジュールされたイベント処理の一般的なパターンは何ですか?
- 26. JSONデータサイズを減らすための一般的な手順は何ですか?
- 27. パスワードに関する一般的な登録エンドポイントのベストプラクティスは何ですか?
- 28. Windows 2000のサポートに関する一般的な合意は何ですか?
- 29. -batchフラグはEmacs(または一般的なUNIX)では何をしますか?
- 30. vimの「選択モード」の一般的な使用例は何ですか?
もう1つの違いは、項目が削除されない場合、書き込み中の任意の数のリーダースレッドによって「HashTable」に安全にアクセスできることです(スレッドではないことです複数のライターにとって安全です)。対照的に、 'Dictionary'は、アドオンのみのシナリオであっても、複数の読者、ゼロのライター以外のシナリオではスレッドセーフではありません。 –
supercat
それは良い点です。ただし、.NET 4では[ConcurrentDictionary](https://msdn.microsoft.com/en-us/library/dd287191%28v=vs.100%29)が導入されています。aspx)は、 'System.Collections.Concurrent'の他のコレクションのようにスレッドセーフです。 –
J0e3gan