HashSet<T> cung cấp constructor nhận IEnumerable<T> cho phép tạo HashSet mới từ một collection đã có (List, Array, HashSet khác...). Constructor này tự động loại bỏ các phần tử trùng lặp.
Ví dụ 1: Tạo HashSet<int> từ HashSet khác
using System;
using System.Collections.Generic;
public class Demo
{
public static void Main()
{
HashSet<int> set1 = new HashSet<int>();
set1.Add(100);
set1.Add(200);
set1.Add(300);
Console.WriteLine("HashSet gốc (set1)...");
foreach (int i in set1)
{
Console.WriteLine(i);
}
// Tạo HashSet mới từ set1
HashSet<int> set2 = new HashSet<int>(set1);
Console.WriteLine("\nHashSet tạo từ collection khác (set2)...");
foreach (int i in set2)
{
Console.WriteLine(i);
}
}
}
Kết quả
HashSet gốc (set1)... 100 200 300 HashSet tạo từ collection khác (set2)... 100 200 300
Ví dụ 2: Tạo từ HashSet có phần tử trùng lặp
using System;
using System.Collections.Generic;
public class Demo
{
public static void Main()
{
HashSet<string> set1 = new HashSet<string>();
set1.Add("Jacob");
set1.Add("Tom");
set1.Add("Harry");
set1.Add("Harry"); // Trùng lặp - bị bỏ qua
set1.Add("Tom"); // Trùng lặp - bị bỏ qua
set1.Add("Harry"); // Trùng lặp - bị bỏ qua
Console.WriteLine("HashSet gốc (set1) - tự động loại trùng...");
foreach (string i in set1)
{
Console.WriteLine(i);
}
// Tạo HashSet mới từ set1
HashSet<string> set2 = new HashSet<string>(set1);
Console.WriteLine("\nHashSet tạo từ collection khác (set2)...");
foreach (string i in set2)
{
Console.WriteLine(i);
}
}
}
Kết quả
HashSet gốc (set1) - tự động loại trùng... Jacob Tom Harry HashSet tạo từ collection khác (set2)... Jacob Tom Harry
Tạo HashSet từ các loại Collection khác
using System;
using System.Collections.Generic;
using System.Linq;
public class Demo
{
public static void Main()
{
// 1. Từ List<T>
List<int> list = new List<int> { 1, 2, 2, 3, 3, 3, 4 };
HashSet<int> fromList = new HashSet<int>(list);
// Kết quả: 1, 2, 3, 4
// 2. Từ Array
string[] array = { "A", "B", "A", "C", "B" };
HashSet<string> fromArray = new HashSet<string>(array);
// Kết quả: A, B, C
// 3. Từ IEnumerable (LINQ)
var numbers = Enumerable.Range(1, 10);
HashSet<int> fromEnumerable = new HashSet<int>(numbers.Where(x => x % 2 == 0));
// Kết quả: 2, 4, 6, 8, 10
// 4. Từ HashSet khác (copy)
HashSet<int> original = new HashSet<int> { 1, 2, 3 };
HashSet<int> copy = new HashSet<int>(original);
}
}
Constructor syntax
public HashSet(IEnumerable<T> collection);
- Tham số:
collection- bất kỳIEnumerable<T> - Hành vi: Sao chép phần tử, tự động loại trùng lặp
- Thứ tự: Không bảo đảm (HashSet unordered)
- Null: Cho phép null nếu T là reference type
So sánh: Constructor vs ToHashSet() (LINQ)
List<int> list = new List<int> { 1, 2, 2, 3 };
// Cách 1: Constructor (từ .NET 2.0)
HashSet<int> set1 = new HashSet<int>(list);
// Cách 2: LINQ ToHashSet() (từ .NET 4.7.2 / .NET Core 2.0)
HashSet<int> set2 = list.ToHashSet();
// Cách 3: Với custom comparer
HashSet<string> set3 = new HashSet<string>(list.Select(x => x.ToString()), StringComparer.OrdinalIgnoreCase);
Lưu ý quan trọng
- Constructor tạo bản sao độc lập - thay đổi set2 không ảnh hưởng set1
- Phần tử trùng lặp trong source collection bị loại bỏ tự động
- HashSet không giữ thứ tự - nếu cần thứ tự, dùng
List<T>hoặcLinkedHashSet(Java) / custom - Hiệu năng: O(n) với n là số phần tử của collection nguồn
- Cần
using System.Collections.Generic
Custom Comparer
// Tạo HashSet case-insensitive từ List
List<string> names = new List<string> { "John", "JOHN", "john", "Mary" };
HashSet<string> uniqueNames = new HashSet<string>(names, StringComparer.OrdinalIgnoreCase);
// Kết quả: "John", "Mary" (chỉ 2 phần tử)