คุณช่วยอธิบายว่าอะไรคือความแตกต่างระหว่างHashSet<T>
และList<T>
ใน. NET
บางทีคุณอาจจะสามารถอธิบายได้ด้วยเช่นในกรณีสิ่งHashSet<T>
ควรได้รับการแนะนำกับList<T>
?
คุณช่วยอธิบายว่าอะไรคือความแตกต่างระหว่างHashSet<T>
และList<T>
ใน. NET
บางทีคุณอาจจะสามารถอธิบายได้ด้วยเช่นในกรณีสิ่งHashSet<T>
ควรได้รับการแนะนำกับList<T>
?
คำตอบ:
ไม่เหมือนรายการ <> ...
HashSet เป็นรายการที่ไม่มีสมาชิกที่ซ้ำกัน
เนื่องจาก HashSet ถูก จำกัด ให้มีเฉพาะรายการที่ไม่ซ้ำกันดังนั้นโครงสร้างภายในจึงเหมาะสำหรับการค้นหา (เปรียบเทียบกับรายการ) - เร็วกว่ามาก
การเพิ่ม HashSet จะส่งคืนบูลีน - false หากการเพิ่มล้มเหลวเนื่องจากมีอยู่แล้วในชุด
สามารถดำเนินการชุดทางคณิตศาสตร์กับชุด: ยูเนี่ยน / แยก / IsSubsetOf ฯลฯ
HashSet ไม่ได้ติดตั้ง ICistlection ของ IList เท่านั้น
คุณไม่สามารถใช้ดัชนีที่มี HashSet เฉพาะตัวแจงนับ
เหตุผลหลักในการใช้ HashSet คือหากคุณสนใจที่จะทำการตั้งค่า
ให้ 2 ชุด: hashSet1 และ hashSet2
//returns a list of distinct items in both sets
HashSet set3 = set1.Union( set2 );
เปรียบเทียบกับการปฏิบัติการที่เทียบเท่าโดยใช้ LINQ นอกจากนี้ยังเป็น neater ที่จะเขียน!
Union
วิธีการ ฉันใช้UnionWith
แทน
เพื่อให้แม่นยำยิ่งขึ้นให้แสดงด้วยตัวอย่าง
คุณไม่สามารถใช้ HashSet เหมือนในตัวอย่างต่อไปนี้
HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
for (int i = 0; i < hashSet1.Count; i++)
Console.WriteLine(hashSet1[i]);
hashSet1[i]
จะทำให้เกิดข้อผิดพลาด:
ไม่สามารถใช้การจัดทำดัชนีด้วย [] กับนิพจน์ประเภท 'System.Collections.Generic.HashSet'
คุณสามารถใช้คำสั่ง foreach:
foreach (var item in hashSet1)
Console.WriteLine(item);
คุณไม่สามารถเพิ่มไอเท็มที่ซ้ำกันลงใน HashSet ได้ในขณะที่ลิสต์อนุญาตให้คุณทำสิ่งนี้และในขณะที่คุณเพิ่มไอเท็มไปยัง HashSet คุณสามารถตรวจสอบว่ามันมีรายการอยู่หรือไม่
HashSet<string> hashSet1 = new HashSet<string>(){"1","2","3"};
if (hashSet1.Add("1"))
Console.WriteLine("'1' is successfully added to hashSet1!");
else
Console.WriteLine("'1' could not be added to hashSet1, because it contains '1'");
HashSet มีฟังก์ชั่นที่มีประโยชน์บางอย่างเช่นIntersectWith
, UnionWith
, IsProperSubsetOf
, ExceptWith
, SymmetricExceptWith
ฯลฯ
IsProperSubsetOf
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
HashSet<string> hashSet3 = new HashSet<string>() { "1", "2", "3", "4", "5" };
if (hashSet1.IsProperSubsetOf(hashSet3))
Console.WriteLine("hashSet3 contains all elements of hashSet1.");
if (!hashSet1.IsProperSubsetOf(hashSet2))
Console.WriteLine("hashSet2 does not contains all elements of hashSet1.");
UnionWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" };
hashSet1.UnionWith(hashSet2); //hashSet1 -> 3, 2, 4, 6, 8
IntersectWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
HashSet<string> hashSet2 = new HashSet<string>() { "2", "4", "6", "8" }
hashSet1.IntersectWith(hashSet2);//hashSet1 -> 4, 8
ExceptWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
hashSet1.ExceptWith(hashSet2);//hashSet1 -> 5, 6
SymmetricExceptWith
:
HashSet<string> hashSet1 = new HashSet<string>() { "1", "2", "3", "5", "6" };
HashSet<string> hashSet2 = new HashSet<string>() { "1", "2", "3", "4" };
hashSet1.SymmetricExceptWith(hashSet2);//hashSet1 -> 4, 5, 6
โดยวิธีการสั่งซื้อจะไม่ถูกเก็บไว้ใน HashSets ในตัวอย่างเราเพิ่มองค์ประกอบ "2" สุดท้าย แต่อยู่ในลำดับที่สอง:
HashSet<string> hashSet1 = new HashSet<string>() { "3", "4", "8" };
hashSet1.Add("1"); // 3, 4, 8, 1
hashSet1.Remove("4"); // 3, 8, 1
hashSet1.Add("2"); // 3, 2 ,8, 1
A HashSet<T>
เป็นคลาสที่ออกแบบมาเพื่อให้คุณO(1)
ค้นหาการบรรจุ (เช่นการสะสมนี้มีวัตถุเฉพาะและบอกคำตอบอย่างรวดเร็ว)
A List<T>
เป็นคลาสที่ออกแบบมาเพื่อให้คอลเลกชันที่มีO(1)
การเข้าถึงแบบสุ่มมากกว่าที่จะเติบโตแบบไดนามิก (คิดว่าอาร์เรย์แบบไดนามิก) คุณสามารถทดสอบการบรรจุได้O(n)
ทันเวลา (ยกเว้นกรณีที่มีการเรียงลำดับรายการจากนั้นคุณสามารถทำการค้นหาแบบไบนารีได้O(log n)
ทันเวลา)
บางทีคุณสามารถอธิบายด้วยตัวอย่างในกรณีที่
HashSet<T>
ควรได้รับการพิจารณาList<T>
O(1)
เมื่อคุณต้องการที่จะทดสอบการบรรจุใน
ใช้List<T>
เมื่อคุณต้องการ:
ถ้าคุณรู้ว่าดัชนีของรายการที่คุณต้องการ (มากกว่าค่าของรายการตัวเอง) O(1)
คือการดึง หากคุณไม่รู้จักดัชนีการค้นหารายการนั้นต้องใช้เวลานานกว่าO(n)
สำหรับการรวบรวมที่ไม่เรียงลำดับ
ใช้Hashset<T>
เมื่อคุณต้องการ:
หากคุณรู้ชื่อของสิ่งที่คุณต้องการค้นหาการค้นหาคือO(1)
(นั่นคือส่วน 'แฮช') มันไม่ได้รักษาลำดับเช่นเดียวกับที่List<T>
ทำและคุณไม่สามารถจัดเก็บรายการที่ซ้ำกัน (การเพิ่มรายการที่ซ้ำกันไม่มีผลนั่นคือส่วน 'ชุด')
ตัวอย่างของการใช้ a Hashset<T>
จะเป็นถ้าคุณต้องการทราบว่าคำที่เล่นในเกม Scrabble เป็นคำที่ถูกต้องในภาษาอังกฤษ (หรือภาษาอื่น ๆ ) ยิ่งไปกว่านั้นถ้าคุณต้องการสร้างบริการบนเว็บที่จะใช้โดยอินสแตนซ์ทั้งหมดของเกมดังกล่าว
A List<T>
จะเป็นโครงสร้างข้อมูลที่ดีสำหรับการสร้างกระดานคะแนนเพื่อติดตามคะแนนผู้เล่น
รายการคือรายการสั่งซื้อ มันคือ
HashSet เป็นชุด มัน:
รายการมีความเหมาะสมมากกว่าเมื่อคุณต้องการเข้าถึงคอลเลกชันของคุณราวกับว่ามันเป็นเหมือนอาร์เรย์ที่คุณสามารถต่อเติมแทรกและลบรายการได้ HashSet เป็นตัวเลือกที่ดีกว่าถ้าคุณต้องการที่จะปฏิบัติต่อคอลเลกชันของคุณเช่น "กระเป๋า" ของรายการที่คำสั่งไม่สำคัญหรือเมื่อคุณต้องการเปรียบเทียบกับชุดอื่น ๆ โดยใช้การดำเนินการเช่น IntersectWith หรือ UnionWith
รายการไม่จำเป็นต้องซ้ำกันในขณะที่ hashset สำหรับ
รายการคือชุดของวัตถุประเภท T ที่เรียงตามลำดับซึ่งแตกต่างจากอาร์เรย์คุณสามารถเพิ่มและลบรายการได้
คุณจะใช้รายการที่คุณต้องการอ้างอิงสมาชิกตามลำดับที่คุณเก็บไว้และคุณกำลังเข้าถึงพวกเขาตามตำแหน่งแทนที่จะเป็นรายการ
HashSet เป็นเหมือนพจนานุกรมที่ไอเท็มนั้นเป็นกุญแจสำคัญเช่นเดียวกับค่าการสั่งซื้อนั้นไม่รับประกัน
คุณจะใช้ HashSet ที่คุณต้องการตรวจสอบว่าวัตถุอยู่ในคอลเลกชัน
List
รักษาคำสั่งซื้อ (เช่นเมื่อมีการเพิ่มสิ่งต่าง ๆ ) แต่จะไม่เรียงลำดับรายการโดยอัตโนมัติ คุณจะต้องโทรหรือการใช้งาน.Sort
SortedList
หากคุณตัดสินใจที่จะใช้โครงสร้างข้อมูลเหล่านี้กับการใช้งานจริงในการพัฒนาที่ขับเคลื่อนด้วยข้อมูล HashSet มีประโยชน์อย่างมากในการทดสอบการจำลองแบบกับแหล่งข้อมูลอะแดปเตอร์สำหรับการล้างข้อมูลและการย้ายข้อมูล
นอกจากนี้หากใช้ DataAnnotations Class เราสามารถใช้ตรรกะของคีย์ในคุณสมบัติคลาสและควบคุมดัชนีธรรมชาติ (คลัสเตอร์หรือไม่) ได้อย่างมีประสิทธิภาพด้วย HashSet ซึ่งจะเป็นเรื่องยากมากในการใช้งานรายการ
ตัวเลือกที่รัดกุมสำหรับการใช้รายการคือการใช้งาน generics สำหรับหลาย ๆ สื่อบน View Model เช่นการส่งรายการของคลาสไปยัง MVC View สำหรับ DropDownList Helper และสำหรับส่งเป็นโครงสร้าง JSON ผ่าน WebApi รายการนี้ช่วยให้ตรรกะการรวบรวมคลาสทั่วไปและมีความยืดหยุ่นสำหรับ "ส่วนต่อประสาน" มากกว่าเช่นวิธีการคำนวณรูปแบบมุมมองเดียวไปยังสื่อที่แตกต่างกัน