เหตุใดจึงเลือกใช้พจนานุกรมมากกว่า Hashtable ใน C #


1395

ในภาษาการเขียนโปรแกรมส่วนใหญ่พจนานุกรมเป็นที่ต้องการมากกว่าแฮชเทเบิล อะไรคือเหตุผลเบื้องหลังนั้น


21
> นี่ไม่จำเป็นต้องเป็นเรื่องจริง ตารางแฮชเป็นการใช้งานของพจนานุกรม โดยทั่วไปแล้วจะเป็นค่าเริ่มต้นใน. NET แต่ไม่ได้นิยามเพียงคำเดียวเท่านั้น ฉันไม่แน่ใจว่าสิ่งนี้เป็นสิ่งจำเป็นตามมาตรฐาน ECMA แต่เอกสาร MSDNเรียกอย่างชัดเจนว่าเป็นการใช้งานเป็น hashtable พวกเขายังให้คลาส SortedList สำหรับเวลาเมื่อมีทางเลือกอื่นที่เหมาะสมกว่า
Promit

15
@Promit ฉันมักจะคิดว่าเป็นการดำเนินการของDictionary Hashtable
b1nary.atr0phy

2
ฉันคิดว่าเหตุผลคือในพจนานุกรมคุณสามารถกำหนดประเภทของคีย์และค่าสำหรับเซลฟีของคุณ Hashtable สามารถนำวัตถุและบันทึกคู่ตาม hash (จาก object.GetHashCode ())
Radinator

2
@Dan การอ้างสิทธิ์ของคุณผิดพลาดมาก ... ตารางแฮชมีเพียงหนึ่งอินสแตนซ์ของแต่ละคีย์เท่านั้นและการค้นหาจะไม่ให้ข้อมูลหลายรายการ หากคุณต้องการเชื่อมโยงหลายค่ากับแต่ละคีย์ให้ทำให้ค่าตารางแฮชเป็นรายการค่า ไม่มีโครงสร้างข้อมูลเช่น "พจนานุกรม" ... พจนานุกรมเป็นเพียงชื่อที่ห้องสมุดบางแห่งใช้สำหรับตารางแฮช เช่นตารางแฮชไม่ใช่ทั่วไป C # 's HashTableเรียกว่า Dictionaryเมื่อพวกเขาได้เพิ่มยาชื่อสามัญเป็นภาษาที่พวกเขาเรียกว่ารุ่นทั่วไป ทั้งสองเป็นตารางแฮช
Jim Balter

3
@Dan การอ้างสิทธิ์ของคุณผิดพลาด ... ตารางแฮช ( en.wikipedia.org/wiki/Hash_table ) เป็นการใช้งานพจนานุกรมโดยเฉพาะอาคาอาร์เรย์ที่เชื่อมโยง ( en.wikipedia.org/wiki/Associative_array ) และการเป็น พจนานุกรมมีเพียงหนึ่งอินสแตนซ์ของแต่ละคีย์เท่านั้นและการค้นหาจะไม่ให้ผลลัพธ์หลายรายการ หากคุณต้องการเชื่อมโยงหลายค่ากับแต่ละคีย์ให้ทำให้ค่าตารางแฮชเป็นรายการค่า และคลาส. NET Dictionary และ Hashtable ต่างก็เป็นทั้งตารางแฮช
Jim Balter

คำตอบ:


1568

สำหรับสิ่งที่คุ้มค่าพจนานุกรมคือ (ในเชิงแนวคิด) ตารางแฮช

หากคุณหมายถึง "ทำไมเราถึงใช้Dictionary<TKey, TValue>คลาสแทนHashtableชั้นเรียน?" นั่นเป็นคำตอบที่ง่าย: Dictionary<TKey, TValue>เป็นประเภททั่วไปHashtableไม่ใช่ นั่นหมายความว่าคุณได้รับความปลอดภัยจากการพิมพ์Dictionary<TKey, TValue>เพราะคุณไม่สามารถแทรกวัตถุสุ่มลงไปได้และคุณไม่จำเป็นต้องโยนค่าที่คุณนำออกไป

สิ่งที่น่าสนใจคือDictionary<TKey, TValue>การนำไปปฏิบัติใน. NET Framework นั้นเป็นไปตามที่Hashtableคุณสามารถบอกได้จากความคิดเห็นนี้ในซอร์สโค้ด:

พจนานุกรมทั่วไปถูกคัดลอกมาจากแหล่งที่มาของ Hashtable

แหล่ง


393
และยังมีคอลเลกชันทั่วไปเป็นจำนวนมากได้เร็วขึ้นไม่มีมวย / unboxing
คริส S

6
ไม่แน่ใจว่าเกี่ยวกับ Hashtable ด้วยกับคำสั่งดังกล่าวข้างต้น แต่สำหรับ ArrayList VS รายการ <T> มันเป็นความจริง
คริส S

36
Hashtable ใช้ Object เพื่อเก็บสิ่งต่าง ๆ ไว้ภายใน (เฉพาะวิธีที่ไม่ใช่แบบทั่วไปที่จะทำ) ดังนั้นมันจะต้องมี box / unbox ด้วย
Guvante

16
@BrianJ: "hash table" (สองคำ) เป็นศัพท์วิทยาศาสตร์คอมพิวเตอร์สำหรับโครงสร้างประเภทนี้ พจนานุกรมเป็นการใช้งานเฉพาะ HashTable สอดคล้องกับพจนานุกรม <object, object> (แม้ว่าจะมีส่วนต่อประสานที่แตกต่างกันเล็กน้อย) แต่ทั้งคู่เป็นการใช้งานของแนวคิดตารางแฮช และแน่นอนว่าจะทำให้เกิดความสับสนมากขึ้นในบางภาษาเรียกว่า "พจนานุกรม" (เช่น Python) ของตารางแฮช - แต่คำศัพท์ CS ที่เหมาะสมยังคงเป็นตารางแฮช
Michael Madsen

32
@BrianJ: ทั้งสองHashTable(ชั้น) และDictionary(ชั้น) เป็นตารางแฮช (แนวคิด) แต่HashTableไม่ได้เป็นDictionaryหรือเป็น พวกเขาจะใช้ในแฟชั่นที่คล้ายกันมากและสามารถกระทำในลักษณะเดียวกับที่ทำ แต่พวกเขาไม่ได้แบ่งปันรหัสโดยตรง DictionaryHashTableDictionary<Object,Object>HashTable
Michael Madsen

625

Dictionary<<< >>> Hashtableความแตกต่าง:

  • ทั่วไป <<< >>> ไม่ใช่ทั่วไป
  • ต้องการการซิงโครไนซ์เธรดของตัวเอง <<< >>> เสนอรุ่นที่ปลอดภัยของเธรดผ่านSynchronized()วิธีการ
  • รายการนับจำนวนKeyValuePair<<< >>> รายการนับจำนวน:DictionaryEntry
  • ใหม่กว่า (> .NET 2.0 ) <<< >>> เก่ากว่า (ตั้งแต่. NET 1.0 )
  • อยู่ในSystem.Collections.Generic <<< >>> อยู่ในSystem.Collections
  • คำขอยกเว้นคีย์ที่ไม่มีอยู่ส่งข้อยกเว้น <<< >>> คำขอไปยังคีย์ที่ไม่มีอยู่ส่งคืนค่า null
  • อาจจะเร็วขึ้นเล็กน้อยสำหรับประเภทของค่า <<< >>> ช้าลงเล็กน้อย (ต้องใช้การชกมวย / ไม่ทำกล่อง) สำหรับประเภทของค่า

Dictionary/ Hashtableความคล้ายคลึงกัน:

  • ทั้งสองเป็นแฮชเทเบิลภายใน== เข้าถึงข้อมูลหลายรายการได้อย่างรวดเร็วตามคีย์
  • ทั้งสองต้องการคีย์ที่ไม่เปลี่ยนรูปแบบและไม่ซ้ำกัน
  • กุญแจของทั้งสองต้องการGetHashCode()วิธีการของตัวเอง

คอลเลกชัน. NET ที่คล้ายกัน (ผู้สมัครใช้แทนพจนานุกรมและ Hashtable):

  • ConcurrentDictionary- เธรดที่ปลอดภัย (สามารถเข้าถึงได้อย่างปลอดภัยจากหลายเธรดพร้อมกัน)
  • HybridDictionary- ประสิทธิภาพที่เพิ่มประสิทธิภาพ (สำหรับบางรายการและหลายรายการ)
  • OrderedDictionary- ค่าสามารถเข้าถึงได้ผ่านดัชนี int (ตามลำดับที่เพิ่มรายการ)
  • SortedDictionary- รายการที่จัดเรียงโดยอัตโนมัติ
  • StringDictionary- พิมพ์อย่างยิ่งและปรับให้เหมาะสมสำหรับสตริง

11
@ Guillaume86 นี่คือสาเหตุที่คุณใช้ TryGetValue แทนmsdn.microsoft.com/en-us/library/bb347013.aspx
Trident D'Gao

2
+1 สำหรับStringDictionary... btw StringDictionaryไม่เหมือนกับDictionary<string, string>เมื่อคุณใช้ Constructor เริ่มต้น
เฉินเฉิน

กระบวนการ ParallelExtensionsExtras @ code.msdn.microsoft.com/windowsdesktop/ …มี ObservableConcurrentDictionary ซึ่งมีความสัมพันธ์ที่ดีกับผู้ใช้พร้อมกัน
VoteCoffee

3
คำอธิบายที่ยอดเยี่ยมเป็นเรื่องดีมากที่คุณได้ระบุความคล้ายคลึงกันเพื่อลดคำถามที่อาจเกิดขึ้นในใจ
mkb


178

เนื่องจากDictionaryเป็นคลาสทั่วไป ( Dictionary<TKey, TValue>) เพื่อให้การเข้าถึงเนื้อหานั้นเป็นประเภทที่ปลอดภัย (เช่นคุณไม่จำเป็นต้องแปลงจากObjectเช่นที่คุณทำกับ a Hashtable)

เปรียบเทียบ

var customers = new Dictionary<string, Customer>();
...
Customer customer = customers["Ali G"];

ถึง

var customers = new Hashtable();
...
Customer customer = customers["Ali G"] as Customer;

อย่างไรก็ตามDictionaryมีการนำมาใช้เป็นตารางแฮชภายในดังนั้นในทางเทคนิคแล้วจะทำงานในลักษณะเดียวกัน


88

FYI: ใน. NET Hashtableเป็นเธรดที่ปลอดภัยสำหรับการใช้งานโดยเธรดตัวอ่านหลายตัวและเธรดการเขียนเดียวในขณะDictionaryที่สมาชิกแบบสแตติกสาธารณะจะปลอดภัยในเธรด แต่สมาชิกอินสแตนซ์ใด ๆ ไม่รับประกันว่าจะปลอดภัยสำหรับเธรด

เราต้องเปลี่ยนพจนานุกรมของเราทั้งหมดกลับเป็นHashtableเพราะเหตุนี้


10
สนุก. ซอร์สโค้ดพจนานุกรม <T> นั้นดูดีกว่าและเร็วกว่ามาก อาจเป็นการดีกว่าถ้าใช้พจนานุกรมและใช้การซิงโครไนซ์ของคุณเอง หากพจนานุกรมต้องอ่านอย่างแน่นอนคุณจำเป็นต้องซิงโครไนซ์การเข้าถึงวิธีการอ่าน / เขียนของพจนานุกรม มันจะล็อคเยอะ แต่มันก็ถูกต้อง
Triynko

10
อีกทางเลือกหนึ่งถ้าการอ่านของคุณไม่จำเป็นต้องเป็นปัจจุบันคุณสามารถถือว่าพจนานุกรมนั้นไม่เปลี่ยนรูป จากนั้นคุณสามารถอ้างอิงถึงพจนานุกรมและเพิ่มประสิทธิภาพโดยไม่ต้องอ่านข้อมูลให้ตรงกันเลย (เนื่องจากมันไม่เปลี่ยนรูปและปลอดภัยต่อเธรด) หากต้องการอัปเดตคุณต้องสร้างสำเนาที่สมบูรณ์ของพจนานุกรมในพื้นหลังจากนั้นเพียงสลับการอ้างอิงกับ Interlocked.CompareExchange (สมมติว่ามีการเขียนเธรดเดียว
Triynko

38
.Net 4.0 ได้เพิ่มConcurrentDictionaryคลาสที่มีวิธีสาธารณะ / การป้องกันทั้งหมดที่นำไปใช้เพื่อความปลอดภัยของเธรด หากคุณไม่ต้องการสนับสนุนแพลตฟอร์มแบบดั้งเดิมสิ่งนี้จะช่วยให้คุณสามารถแทนที่Hashtableรหัสแบบมัลติเธรดใน: msdn.microsoft.com/en-us/library/dd287191.aspx
Dan Is Fiddling โดย Firelight

ไม่ระบุชื่อเพื่อช่วยเหลือ คำตอบที่ยอดเยี่ยม
unkulunkulu

5
ฉันจำได้ว่าการอ่านว่า HashTable เป็นเพียงผู้อ่านด้ายเขียนที่ปลอดภัยในสถานการณ์ที่ข้อมูลไม่เคยถูกลบออกจากตาราง หากผู้อ่านกำลังขอรายการที่อยู่ในตารางขณะที่รายการอื่นกำลังถูกลบและผู้อ่านต้องการค้นหามากกว่าหนึ่งแห่งสำหรับรายการเป็นไปได้ว่าในขณะที่ผู้อ่านกำลังค้นหาผู้เขียนอาจย้ายรายการ จากสถานที่ที่ยังไม่ได้ตรวจสอบสถานที่ซึ่งมีผลให้รายงานเท็จว่าไม่มีรายการ
supercat

68

ใน. NET ความแตกต่างระหว่างDictionary<,>และHashTableส่วนใหญ่เป็นแบบเก่าดังนั้นคุณจะได้รับประโยชน์ทั้งหมดของ generics ในแง่ของการตรวจสอบชนิดคงที่ (และการชกมวยลดลง แต่นี่ไม่ใหญ่เท่าที่คนมักจะคิด แง่ของประสิทธิภาพ - มีค่าใช้จ่ายหน่วยความจำที่แน่นอนในการชกมวยอยู่)


34

ผู้คนกำลังพูดกันว่าพจนานุกรมเหมือนกันกับตารางแฮช

สิ่งนี้ไม่เป็นความจริง ตารางแฮชเป็นวิธีหนึ่งในการนำพจนานุกรมมาใช้ โดยทั่วไปจะเป็นแบบนั้นและอาจเป็นค่าเริ่มต้นใน. NET ในDictionaryคลาส แต่ไม่ได้นิยามเพียงอันเดียว

คุณสามารถใช้พจนานุกรมอย่างเท่าเทียมกันโดยใช้รายการที่เชื่อมโยงหรือแผนผังการค้นหามันจะไม่มีประสิทธิภาพเท่าไหร่ (สำหรับการวัดที่มีประสิทธิภาพ)


4
MS docs กล่าวว่า: "การดึงค่าโดยใช้คีย์นั้นเร็วมากใกล้กับ O (1) เนื่องจากคลาส Dictionary <(ของ <(TKey, TValue>)>) มีการใช้งานเป็นตารางแฮช" - ดังนั้นคุณจึงควรได้รับการรับประกัน Hashtable Dictionary<K,V>เมื่อจัดการกับ IDictionary<K,V>จะเป็นอะไรแม้ว่า :)
snemarch

13
@ rix0rrr - ฉันคิดว่าคุณมีที่อยู่ข้างหลังพจนานุกรมใช้ HashTable ไม่ใช่ HashTable ใช้พจนานุกรม
โจเซฟแฮมิลตัน

8
@JosephHamilton - rix0rrr ได้มันขวา: "ตารางแฮชคือการดำเนินการของพจนานุกรม ." เขาหมายถึงแนวคิด "พจนานุกรม" ไม่ใช่คลาส (หมายเหตุตัวพิมพ์เล็ก) โดยทั่วไปแล้วตารางแฮชจะใช้อินเทอร์เฟซพจนานุกรม ใน. NET พจนานุกรมใช้ตารางแฮชเพื่อใช้งาน IDictionary มันยุ่งเหยิง;)
Robert Hensing

ฉันกำลังพูดถึงใน. NET เพราะนั่นคือสิ่งที่เขาอ้างอิงในการตอบสนองของเขา
โจเซฟแฮมิลตัน

2
@JosephHamilton: การดำเนินการ (หรือการดำเนินการ ) ไม่ได้จากระยะไกลหมายถึงสิ่งเดียวกับการใช้งาน ค่อนข้างตรงกันข้าม บางทีมันอาจจะชัดเจนกว่านี้ถ้าเขาบอกว่ามันแตกต่างกันเล็กน้อย (แต่มีความหมายเหมือนกัน): "ตารางแฮชเป็นวิธีหนึ่งในการนำพจนานุกรมมาใช้" นั่นคือถ้าคุณต้องการฟังก์ชั่นของพจนานุกรมวิธีหนึ่งในการทำเช่นนั้น (เพื่อใช้พจนานุกรม) คือการใช้ hashtable
ToolmakerSteve

21

Collections& Genericsมีประโยชน์สำหรับการจัดการกลุ่มวัตถุ ใน .NET, คอลเลกชันทั้งหมดวัตถุมาภายใต้อินเตอร์เฟซIEnumerableซึ่งในทางกลับกันมีและArrayList(Index-Value)) HashTable(Key-Value)หลังจาก .NET Framework 2.0 ArrayListและHashTableถูกแทนที่ด้วยและList Dictionaryตอนนี้Arraylist& HashTableจะไม่ใช้ในโครงการปัจจุบันมากขึ้น

มาถึงความแตกต่างระหว่างHashTable& Dictionary, Dictionaryเป็นทั่วไปในขณะที่Hastableไม่ได้ทั่วไป เราสามารถเพิ่มประเภทของวัตถุใด ๆHashTableแต่ในขณะที่ดึงเราจำเป็นต้องโยนมันลงในประเภทที่ต้องการ ดังนั้นจึงไม่ปลอดภัยพิมพ์ แต่dictionaryในขณะที่ประกาศตัวเองเราสามารถระบุประเภทของคีย์และค่าดังนั้นจึงไม่จำเป็นต้องร่ายขณะดึงข้อมูล

ลองดูตัวอย่าง:

HashTable

class HashTableProgram
{
    static void Main(string[] args)
    {
        Hashtable ht = new Hashtable();
        ht.Add(1, "One");
        ht.Add(2, "Two");
        ht.Add(3, "Three");
        foreach (DictionaryEntry de in ht)
        {
            int Key = (int)de.Key; //Casting
            string value = de.Value.ToString(); //Casting
            Console.WriteLine(Key + " " + value);
        }

    }
}

พจนานุกรม,

class DictionaryProgram
{
    static void Main(string[] args)
    {
        Dictionary<int, string> dt = new Dictionary<int, string>();
        dt.Add(1, "One");
        dt.Add(2, "Two");
        dt.Add(3, "Three");
        foreach (KeyValuePair<int, String> kv in dt)
        {
            Console.WriteLine(kv.Key + " " + kv.Value);
        }
    }
}

2
แทนที่จะกำหนดประเภทข้อมูลสำหรับ KeyValuePair อย่างชัดเจนเราสามารถใช้ var ดังนั้นสิ่งนี้จะลดการพิมพ์ - foreach (var kv ใน dt) ... เพียงแค่ข้อเสนอแนะ
รอน

16

พจนานุกรม:

  • มันจะส่งกลับ / ส่งข้อยกเว้นถ้าเราพยายามหากุญแจที่ไม่มีอยู่

  • มันเร็วกว่า Hashtable เพราะไม่มีการชกมวย

  • เฉพาะสมาชิกแบบสแตติกสาธารณะเท่านั้นที่จะปลอดภัยในเธรด

  • พจนานุกรมเป็นประเภททั่วไปซึ่งหมายความว่าเราสามารถใช้กับประเภทข้อมูลใด ๆ (เมื่อสร้างจะต้องระบุประเภทข้อมูลสำหรับคีย์และค่า)

    ตัวอย่าง: Dictionary<string, string> <NameOfDictionaryVar> = new Dictionary<string, string>();

  • Dictionay เป็นการใช้งานแบบปลอดภัยของ Hashtable KeysและValuesพิมพ์อย่างยิ่ง

Hashtable:

  • มันจะคืนค่า null ถ้าเราพยายามหากุญแจที่ไม่มีอยู่

  • ช้ากว่าพจนานุกรมเนื่องจากต้องใช้มวยและไม่ได้เปิดใช้งาน

  • สมาชิกทั้งหมดใน Hashtable เป็นเธรดที่ปลอดภัย

  • Hashtable ไม่ใช่ประเภททั่วไป

  • Hashtable เป็นโครงสร้างข้อมูลที่พิมพ์อย่างอิสระเราสามารถเพิ่มคีย์และค่าของประเภทใดก็ได้


"จะส่งกลับ / ส่งข้อยกเว้นถ้าเราพยายามหารหัสที่ไม่มีอยู่" ไม่ใช่ถ้าคุณใช้Dictionary.TryGetValue
Jim Balter

16

การตรวจสอบอย่างละเอียดของโครงสร้างข้อมูลโดยใช้บทความC #บน MSDN ระบุว่ามีความแตกต่างใน กลยุทธ์การแก้ปัญหาการชนกันของข้อมูล :

คลาส Hashtable ใช้เทคนิคที่เรียกว่าrehashing

การทำความร้อนซ้ำทำงานดังนี้: มีชุดของฟังก์ชัน hash ที่แตกต่างกัน H 1 ... H nและเมื่อแทรกหรือดึงรายการจากตารางแฮชเริ่มแรกใช้ฟังก์ชันH 1 Hash หากนำไปสู่การนี้เพื่อชน H 2พยายามแทนและเป็นต้นไปถึง H nถ้าจำเป็น

พจนานุกรมใช้เทคนิคที่เรียกว่าการผูกมัด

ในกรณีที่มีการขัดสีใหม่การแฮชจะถูกคำนวณใหม่และมีการลองใช้สล็อตใหม่ที่สอดคล้องกับแฮช ด้วยการผูกมัด แต่โครงสร้างข้อมูลทุติยภูมิที่ถูกนำมาใช้ในการถือชนใดโดยเฉพาะแต่ละช่องในพจนานุกรมมีองค์ประกอบหลายอย่างที่จับคู่กับที่เก็บข้อมูล ในกรณีที่มีการชนกันองค์ประกอบการชนกันจะถูกนำเสนอในรายการของที่เก็บข้อมูล


16

ตั้งแต่. NET Framework 3.5 นอกจากนี้ยังมีHashSet<T>ที่ให้ข้อดีทั้งหมดของDictionary<TKey, TValue>ถ้าคุณต้องการเพียงคีย์และไม่มีค่า

ดังนั้นถ้าคุณใช้Dictionary<MyType, object>และมักจะตั้งค่าเป็นเพื่อจำลองประเภทตารางแฮชปลอดภัยคุณอาจควรพิจารณาเปลี่ยนไปnullHashSet<T>


14

เป็นโครงสร้างข้อมูลหลวมพิมพ์เพื่อให้คุณสามารถเพิ่มคีย์และค่านิยมของชนิดใดHashtable ๆ ระดับเป็นชนิดที่ปลอดภัยการดำเนินงานและคีย์และค่าพิมพ์มั่น เมื่อสร้างอินสแตนซ์คุณต้องระบุประเภทข้อมูลสำหรับทั้งคีย์และค่าHashtableDictionaryHashtableDictionary


11

ขอให้สังเกตว่า MSDN พูดว่า: "พจนานุกรม <(ของ <(TKey, TValue>)>) มีการใช้งานคลาสเป็นตารางแฮช " ไม่ใช่ "พจนานุกรม <(ของ <(TKey, TValue>)>) ระดับถูกนำมาใช้เป็นHashTable "

พจนานุกรมไม่ได้ถูกนำมาใช้เป็น HashTable แต่ถูกนำไปใช้ตามแนวคิดของตารางแฮช การใช้งานไม่เกี่ยวข้องกับคลาส HashTable เนื่องจากการใช้ Generics แม้ว่า Microsoft ภายในสามารถใช้รหัสเดียวกันและแทนที่สัญลักษณ์ของประเภทวัตถุด้วย TKey และ TValue

ใน. NET 1.0 Generics ไม่มีอยู่จริง นี่คือจุดเริ่มต้นของ HashTable และ ArrayList


คุณสามารถแก้ไขคำพูด MSDN นั้นได้หรือไม่? มีบางอย่างขาดหายไปหรือผิด มันไม่ได้เป็นไวยากรณ์และค่อนข้างเข้าใจยาก
Peter Mortensen

10

HashTable:

คีย์ / ค่าจะถูกแปลงเป็นประเภทวัตถุ (มวย) ในขณะที่เก็บไว้ในกอง

คีย์ / ค่าต้องถูกแปลงเป็นชนิดที่ต้องการขณะอ่านจากกอง

การดำเนินการเหล่านี้มีค่าใช้จ่ายสูงมาก เราจำเป็นต้องหลีกเลี่ยงการชกมวย / unboxing มากที่สุด

พจนานุกรม:ตัวแปรทั่วไปของ HashTable

ไม่มีชกมวย / unboxing ไม่จำเป็นต้องมีการแปลง


8

วัตถุ Hashtable ประกอบด้วยถังที่มีองค์ประกอบของคอลเลกชัน ถังเป็นกลุ่มย่อยเสมือนจริงขององค์ประกอบภายใน Hashtable, ซึ่งทำให้การค้นหาและเรียกง่ายและเร็วกว่าในคอลเลกชันมากที่สุด

คลาส Dictionary มีฟังก์ชันการทำงานเช่นเดียวกับคลาส Hashtable พจนานุกรมประเภทที่เฉพาะเจาะจง (นอกเหนือจากวัตถุ) มีประสิทธิภาพที่ดีกว่า Hashtableสำหรับประเภทค่าเนื่องจากองค์ประกอบของ Hashtable เป็นประเภทวัตถุและดังนั้นโดยทั่วไปแล้วมวยและการ unboxing จะเกิดขึ้นหากการจัดเก็บหรือดึงค่าประเภท

สำหรับการอ่านเพิ่มเติม: ประเภทHashtable และพจนานุกรม


7

ข้อแตกต่างที่สำคัญอีกประการหนึ่งคือ Hashtable ปลอดภัยสำหรับเธรด Hashtable มีความปลอดภัยในตัวเครื่องอ่าน / ตัวเขียน (MR / SW) หลายเธรดซึ่งหมายความว่า Hashtable อนุญาตให้ตัวเขียนหนึ่งตัวพร้อมกับเครื่องอ่านหลายตัวโดยไม่ล็อค

ในกรณีของพจนานุกรมไม่มีความปลอดภัยของเธรด; ถ้าคุณต้องการความปลอดภัยของเธรดคุณต้องใช้การซิงโครไนซ์ของคุณเอง

หากต้องการรายละเอียดเพิ่มเติม:

Hashtable ให้ความปลอดภัยของเธรดผ่านSynchronizedคุณสมบัติซึ่งจะส่งคืน wrapper ที่ปลอดภัยสำหรับรอบคอลเลกชัน เสื้อคลุมทำงานโดยการล็อคคอลเลกชันทั้งหมดในทุกการดำเนินการเพิ่มหรือลบ ดังนั้นแต่ละเธรดที่พยายามเข้าถึงคอลเลกชันจะต้องรอการเลี้ยวเพื่อล็อคหนึ่งครั้ง สิ่งนี้ไม่สามารถปรับขนาดได้และอาจทำให้ประสิทธิภาพลดลงอย่างมากสำหรับคอลเลกชันขนาดใหญ่ นอกจากนี้การออกแบบไม่ได้รับการปกป้องอย่างสมบูรณ์จากสภาพการแข่งขัน

คลาสคอลเลกชัน. NET Framework 2.0 เช่นList<T>, Dictionary<TKey, TValue>อื่น ๆ ไม่มีการซิงโครไนซ์เธรดใด ๆ รหัสผู้ใช้จะต้องระบุการซิงโครไนซ์ทั้งหมดเมื่อมีการเพิ่มหรือลบรายการในหลายเธรดพร้อมกัน

ถ้าคุณต้องการความปลอดภัยการพิมพ์เช่นเดียวกับความปลอดภัยของเธรดใช้คลาสคอลเลกชันที่เกิดขึ้นพร้อมกันใน. NET Framework อ่านเพิ่มเติมที่นี่

ข้อแตกต่างเพิ่มเติมคือเมื่อเราเพิ่มหลายรายการในพจนานุกรมลำดับที่เพิ่มรายการนั้นจะถูกเก็บไว้ เมื่อเราดึงรายการจากพจนานุกรมเราจะได้รับบันทึกในลำดับเดียวกันกับที่เราได้แทรกไว้ ในขณะที่ Hashtable ไม่รักษาลำดับการแทรก


จากสิ่งที่ฉันเข้าใจHashsetค้ำประกัน MR / SW หัวข้อความปลอดภัยในสถานการณ์การใช้งานที่ไม่เกี่ยวข้องกับการลบ ฉันคิดว่ามันอาจมีจุดประสงค์ที่จะให้ความปลอดภัยของ MR / SW อย่างเต็มที่ แต่การจัดการการลบอย่างปลอดภัยจะเพิ่มค่าใช้จ่ายของความปลอดภัยของ MR / SW อย่างมาก ในขณะที่การออกแบบของDictionaryสามารถให้ความปลอดภัยของ MR / SW ในราคาที่ถูกที่สุดในสถานการณ์แบบไม่ลบฉันคิดว่า MS ต้องการหลีกเลี่ยงการดำเนินการกับสถานการณ์ที่ไม่ลบในรูปแบบ "พิเศษ"
supercat

5

อีกหนึ่งความแตกต่างที่ฉันคิดได้คือ:

เราไม่สามารถใช้พจนานุกรม <KT, VT> (generics) กับบริการบนเว็บได้ เหตุผลก็คือไม่มีมาตรฐานบริการเว็บรองรับมาตรฐานทั่วไป


เราสามารถใช้รายการทั่วไป (List <string>) ในเว็บเซอร์วิสที่ใช้สบู่ แต่เราไม่สามารถใช้พจนานุกรม (หรือ hashtable) ในเว็บเซอร์ ฉันคิดว่าเหตุผลในการนี้คือ. xnetserializer ไม่สามารถจัดการวัตถุพจนานุกรม
Siddharth

5

Dictionary<> เป็นประเภททั่วไปดังนั้นจึงเป็นประเภทที่ปลอดภัย

คุณสามารถแทรกค่าประเภทใดก็ได้ใน HashTable และบางครั้งอาจทำให้เกิดข้อยกเว้น แต่Dictionary<int>จะยอมรับเฉพาะค่าจำนวนเต็มเท่านั้นและในทำนองเดียวกันDictionary<string>จะยอมรับเฉพาะสตริงเท่านั้น

ดังนั้นมันจะดีกว่าที่จะใช้แทนDictionary<>HashTable


0

ในภาษาการเขียนโปรแกรมส่วนใหญ่พจนานุกรมเป็นที่ต้องการมากกว่าแฮชเทเบิล

ผมไม่คิดว่านี่เป็นความจริงที่จำเป็นต้องภาษาส่วนใหญ่จะมีหนึ่งหรืออื่น ๆ ขึ้นอยู่กับคำศัพท์ที่พวกเขาต้องการ

อย่างไรก็ตามใน C # เหตุผลที่ชัดเจน (สำหรับฉัน) ก็คือ C # HashTables และสมาชิกคนอื่น ๆ ของ System.Collections namespace ส่วนใหญ่ล้าสมัยไปแล้ว พวกเขาอยู่ใน c # V1.1 พวกเขาถูกแทนที่จาก C # 2.0 โดยคลาส Generic ใน System.Collections.Generic namespace


ข้อดีอย่างหนึ่งของ hashtable เหนือพจนานุกรมคือถ้าไม่มีคีย์ในพจนานุกรมมันจะทำให้เกิดข้อผิดพลาด ถ้าไม่มีคีย์ใน hashtable มันจะส่งคืนค่าว่าง
Bill Norman

ใน C # ฉันยังคงหลีกเลี่ยงการใช้ System.Collections.Hashtable เนื่องจากไม่มีข้อได้เปรียบของยาชื่อสามัญ คุณสามารถใช้ TryGetValue หรือ HasKey ของ Dictionary หากคุณไม่ทราบว่าจะมีรหัสหรือไม่
kristianp

อ๊ะไม่ใช่ HasKey มันควรจะมีKeyKey
kristianp

-3

ตามที่ฉันเห็นโดยใช้. NET Reflector :

[Serializable, ComVisible(true)]
public abstract class DictionaryBase : IDictionary, ICollection, IEnumerable
{
    // Fields
    private Hashtable hashtable;

    // Methods
    protected DictionaryBase();
    public void Clear();
.
.
.
}
Take note of these lines
// Fields
private Hashtable hashtable;

ดังนั้นเราจึงมั่นใจได้ว่า DictionaryBase ใช้ HashTable ภายใน


16
System.Collections.Generic.Dictionary <TKey, TValue> ไม่ได้มาจาก DictionaryBase
snemarch

"ดังนั้นเราจึงมั่นใจได้ว่า DictionaryBase ใช้ HashTable ภายใน" - ดี แต่ไม่มีอะไรเกี่ยวข้องกับคำถาม
Jim Balter
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.