Collections Inti

List<T>, Dictionary<K,V>, HashSet<T>, dan cara memilih di antaranya.

Daftar isi

Collection adalah struktur data yang menampung banyak elemen dalam satu variabel, sedangkan generic berarti tipe elemennya ditetapkan lewat parameter tipe sehingga ketidakcocokan tipe terdeteksi pada saat kompilasi. Topik ini membahas tiga collection dasar .NET, yaitu List<T> untuk data berurutan, Dictionary<K,V> untuk pencarian berdasarkan kunci, dan HashSet<T> untuk elemen yang unik. Setiap collection disertai contoh yang benar-benar dijalankan, kemudian ditutup dengan panduan memilih di antara ketiganya.

List untuk data berurutan#

List<T> menyimpan elemen dengan urutan yang dijaga dan mengizinkan akses langsung ke posisi tertentu melalui indeks. Elemen baru ditambahkan dengan metode Add, jumlahnya dibaca dari property Count, dan elemen tertentu diakses lewat penanda indeks. Indeks dimulai dari 0, sedangkan penanda ^1 menunjuk elemen dari akhir. Metode Remove menghapus elemen pertama yang nilainya cocok dengan argumennya. Contoh berikut menunjukkan operasi dasar tersebut pada daftar nilai ujian.

csharp Contoh: operasi dasar List
// Contoh: List menyimpan nilai ujian dengan urutan terjaga
List<int> nilaiUjian = new() { 84, 71, 90 };
nilaiUjian.Add(66);
Console.WriteLine($"Jumlah nilai: {nilaiUjian.Count}");
Console.WriteLine($"Nilai pertama: {nilaiUjian[0]}");
Console.WriteLine($"Nilai terakhir: {nilaiUjian[^1]}");
nilaiUjian.Remove(71);
Console.WriteLine($"Setelah Remove(71): {string.Join(", ", nilaiUjian)}");
text Keluaran
Jumlah nilai: 4
Nilai pertama: 84
Nilai terakhir: 66
Setelah Remove(71): 84, 90, 66

Nilai Count berubah dari 3 menjadi 4 setelah Add(66) dijalankan, sehingga kapasitas penyimpanan bertambah secara otomatis tanpa dikelola secara manual. Penanda [^1] menghasilkan 66 karena elemen itu menempati posisi terakhir, sedangkan [0] tetap menghasilkan 84 karena posisi awalnya tidak berubah. Metode Remove(71) menghapus satu elemen bernilai 71, dan elemen di belakangnya bergeser mengisi posisi yang kosong. List<T> mengizinkan duplikat, sehingga dua elemen dengan nilai yang sama tetap tersimpan berdua.

Selain Add dan Remove, metode yang sering digunakan mencakup Insert untuk menyisipkan elemen pada posisi tertentu, Clear untuk mengosongkan seluruh isi, dan Contains untuk memeriksa keberadaan nilai. Penelusuran lewat foreach menampilkan elemen menurut urutannya, sehingga daftar nilai ujian tetap terbaca dari yang pertama sampai yang terakhir. Seluruh operasi ini bekerja di atas array internal yang dikelola List secara otomatis, sehingga kapasitasnya menyesuaikan diri tanpa campur tangan.

Dictionary untuk pencarian berdasarkan kunci#

Dictionary<K,V> menyimpan pasangan kunci dan nilai, kemudian mengambil nilai berdasarkan kuncinya tanpa menelusuri seluruh isi. Kunci harus unik, sedangkan nilai boleh sama antarpasangan. Penugasan lewat penanda indeks menambahkan pasangan baru ketika kunci belum ada dan mengganti nilai ketika kuncinya sudah terdaftar. Contoh berikut menggunakan dictionary untuk memetakan hari piket ke nama petugas.

csharp Contoh: Dictionary jadwal piket dengan TryGetValue
// Contoh: Dictionary memetakan hari piket ke nama petugas
Dictionary<string, string> jadwalPiket = new()
{
    ["Senin"] = "Ali",
    ["Selasa"] = "Budi",
    ["Rabu"] = "Citra"
};
jadwalPiket["Kamis"] = "Dewi";
Console.WriteLine($"Piket Rabu: {jadwalPiket["Rabu"]}");

if (jadwalPiket.TryGetValue("Jumat", out string? petugas))
{
    Console.WriteLine($"Piket Jumat: {petugas}");
}
else
{
    Console.WriteLine("Jumat belum memiliki petugas piket");
}
text Keluaran
Piket Rabu: Citra
Jumat belum memiliki petugas piket

Metode TryGetValue mengembalikan true ketika kunci ditemukan dan menampung nilainya pada variabel keluaran petugas, serta mengembalikan false tanpa melempar exception ketika kunci tidak ada. Pola inilah yang disarankan untuk kunci yang keberadaannya belum pasti, karena akses lewat penanda indeks berperilaku sebaliknya.

Perilaku pada peringatan di atas terlihat pada contoh berikut. Exception ditangkap dengan try-catch, kemudian pesan aslinya dicetak.

csharp Contoh: KeyNotFoundException saat kunci tidak terdaftar
// Contoh: akses indexer Dictionary dengan kunci yang belum terdaftar
Dictionary<string, string> jadwalPiket = new() { ["Senin"] = "Ali" };

try
{
    Console.WriteLine(jadwalPiket["Jumat"]);
}
catch (KeyNotFoundException ex)
{
    Console.WriteLine(ex.Message);
}
text Keluaran
The given key 'Jumat' was not present in the dictionary.

Dictionary juga dapat ditelusuri dengan foreach, dan setiap elemennya bertipe KeyValuePair<K,V> yang membawa property Key serta Value. Penelusuran seperti itu berguna untuk menampilkan seluruh isi jadwal piket tanpa mengetahui kuncinya lebih dahulu. Perlu diingat bahwa urutan pasangan pada Dictionary tidak dijanjikan mengikuti waktu penyisipannya, sehingga tampilan yang menuntut urutan tetap diurutkan secara eksplisit.

HashSet untuk elemen yang unik#

HashSet<T> menyimpan setiap nilai paling banyak satu kali, sehingga cocok untuk data yang tidak boleh berduplikat seperti daftar hadir. Metode Add mengembalikan true ketika nilai benar-benar ditambahkan dan false ketika nilainya sudah ada, sehingga keberhasilan penambahan dapat diperiksa tanpa pemeriksaan tambahan. Contoh berikut menunjukkan perilaku tersebut.

csharp Contoh: HashSet menolak duplikat secara diam-diam
// Contoh: HashSet menolak duplikat secara diam-diam
HashSet<string> pesertaHadir = new() { "Ali", "Budi", "Citra" };
Console.WriteLine($"Tambah Budi lagi: {pesertaHadir.Add("Budi")}");
Console.WriteLine($"Tambah Dewi: {pesertaHadir.Add("Dewi")}");
Console.WriteLine($"Jumlah peserta unik: {pesertaHadir.Count}");
text Keluaran
Tambah Budi lagi: False
Tambah Dewi: True
Jumlah peserta unik: 4

Pemanggilan Add("Budi") yang kedua mengembalikan false dan isi collection tidak berubah, sedangkan Add("Dewi") mengembalikan true karena Dewi belum terdaftar. Metode Contains pada HashSet<T> juga berjalan cepat karena pencariannya diarahkan oleh nilai hash, yaitu penanda numerik yang dihitung dari setiap elemen, sedangkan Contains pada List<T> menelusuri elemen satu per satu.

Memilih collection yang sesuai#

Tabel berikut merangkum kapan ketiga collection di atas dipilih.

KebutuhanPilihanAlasan
Urutan penting dan akses lewat indeksList<T>posisi elemen dijaga dan indeks tersedia
Pencarian cepat berdasarkan kunciDictionary<K,V>nilai diambil langsung dari kuncinya
Keunikan nilai dan pemeriksaan keanggotaanHashSet<T>duplikat ditolak dan pencarian berbasis hash

Pertanyaan penentuannya sederhana, yaitu bagaimana data akan diakses paling sering. Daftar nilai ujian diakses menurut posisinya, sehingga List<T> tepat. Jadwal piket diakses menurut harinya, sehingga Dictionary<K,V> tepat. Daftar hadir ditanyakan keanggotaannya, sehingga HashSet<T> tepat. Karena ketiganya mengimplementasikan antarmuka enumerasi yang sama, satu collection juga dapat menggantikan yang lain dengan perubahan kecil, tetapi pilihan yang tepat sejak awal menghindarkan konversi yang tidak perlu.

Contoh program utuh#

Program berikut merangkum ketiga collection dalam satu berkas agar perilakunya dapat dibandingkan secara langsung.

csharp Program.cs
// Program contoh List, Dictionary, dan HashSet

// List<T>: urutan penting dan elemen diakses lewat indeks
List<int> nilaiUjian = new() { 84, 71, 90, 66 };
nilaiUjian.Add(77);
Console.WriteLine($"Jumlah nilai: {nilaiUjian.Count}");
Console.WriteLine($"Nilai pertama: {nilaiUjian[0]}");
Console.WriteLine($"Nilai terakhir: {nilaiUjian[^1]}");

// Dictionary<K,V>: pencarian berdasarkan kunci tanpa menelusuri seluruh isi
Dictionary<string, string> jadwalPiket = new()
{
    ["Senin"] = "Ali",
    ["Selasa"] = "Budi",
    ["Rabu"] = "Citra"
};
if (jadwalPiket.TryGetValue("Rabu", out string? petugas))
{
    Console.WriteLine($"Piket Rabu: {petugas}");
}
Console.WriteLine($"Jumat terdaftar: {jadwalPiket.ContainsKey("Jumat")}");

// HashSet<T>: elemen unik tanpa duplikat
HashSet<string> pesertaHadir = new() { "Ali", "Budi", "Citra" };
Console.WriteLine($"Tambah Budi lagi: {pesertaHadir.Add("Budi")}");
Console.WriteLine($"Tambah Dewi: {pesertaHadir.Add("Dewi")}");
Console.WriteLine($"Jumlah peserta unik: {pesertaHadir.Count}");
text Keluaran
Jumlah nilai: 5
Nilai pertama: 84
Nilai terakhir: 77
Piket Rabu: Citra
Jumat terdaftar: False
Tambah Budi lagi: False
Tambah Dewi: True
Jumlah peserta unik: 4

Jalankan program tersebut dari folder topik dengan perintah berikut.

bash
# aktifkan .NET yang terpasang di sandbox
export DOTNET_ROOT=/home/kal/.dotnet PATH=/home/kal/.dotnet:$PATH DOTNET_CLI_TELEMETRY_OPTOUT=1 DOTNET_NOLOGO=1
# jalankan program contoh dari folder topik
dotnet run --file Program.cs
text Keluaran
Jumlah nilai: 5
Nilai pertama: 84
Nilai terakhir: 77
Piket Rabu: Citra
Jumat terdaftar: False
Tambah Budi lagi: False
Tambah Dewi: True
Jumlah peserta unik: 4

Kesalahan umum#

  • Membaca nilai Dictionary lewat penanda indeks untuk kunci yang belum pasti terdaftar. Exception KeyNotFoundException muncul pada runtime, dan perbaikannya adalah menggunakan TryGetValue sebelum akses dilakukan.
  • Mengira HashSet menjaga urutan penyisipan. Urutan penelusurannya tidak dijanjikan, sehingga kebutuhan urutan sebaiknya dilayani List<T> atau pengurutan eksplisit.
  • Menambah atau menghapus elemen collection ketika foreach sedang menelusurinya. Exception InvalidOperationException muncul pada runtime, dan perbaikannya adalah menelusuri salinannya terlebih dahulu, misalnya dengan ToList().

Ringkasan#

  • List<T> menjaga urutan elemen, mendukung akses lewat indeks, dan mengizinkan duplikat.
  • Dictionary<K,V> memetakan kunci yang unik ke nilai, dan TryGetValue lebih aman daripada penanda indeks untuk kunci yang belum pasti.
  • HashSet<T> menampung setiap nilai satu kali, mengembalikan false dari Add untuk duplikat, dan cepat untuk pemeriksaan keanggotaan.
  • Pilihan collection mengikuti pola akses data, yaitu urutan, kunci, atau keunikan.

Referensi#