Masukkan Password
11 Features of List in dart | Characteristics of List | Dart Tutorial #10
Video ini membahas 7 fitur penting pada List di Dart yang cukup sering dipakai saat membuat aplikasi Flutter.
Saya akan jelaskan bukan hanya βapa yang dikatakan videoβ, tetapi juga apa maksud kodenya, kapan digunakan, dan jebakan yang perlu kamu pahami.
Gambaran besar
7 poin yang dibahas:
- **Collection
ifdan collectionfor - Spread operator
... RangeErrorketika index di luar batas- Perbedaan
for-indenganforbiasa ketika memodifikasi List Listadalah abstract class, tetapi bisa dibuat dengan constructor- List di dalam List β 2D List / matrix
- Mengubah
lengthList β muncul elemennull
Kita bahas satu per satu.
1. Collection if dan Collection for
Ini salah satu fitur Dart yang sangat berguna.
Dart memungkinkan kita membuat isi List menggunakan:
iffor
langsung di dalam [].
Contoh sederhana:
var items = [
10,
20,
if (10 > 5)
30,
for (var i = 1; i <= 5; i++)
i,
];
print(items);
Hasil:
[10, 20, 30, 1, 2, 3, 4, 5]
Sekarang mari kita pahami prosesnya.
Bagian pertama
10,
20,
Ini langsung dimasukkan ke List.
Sehingga sementara:
[10, 20]
Bagian kedua
if (10 > 5)
30,
Dart mengecek:
10 > 5
Hasilnya:
true
Maka 30 dimasukkan.
[10, 20, 30]
Kalau kondisinya:
if (10 > 50)
30,
maka:
10 > 50
false
Akibatnya 30 tidak dimasukkan.
Hasil:
[10, 20]
Collection for
Sekarang lihat:
for (var i = 1; i <= 5; i++)
i,
Ini berarti:
i = 1 β masukkan 1
i = 2 β masukkan 2
i = 3 β masukkan 3
i = 4 β masukkan 4
i = 5 β masukkan 5
Sehingga:
[10, 20, 30, 1, 2, 3, 4, 5]
Kenapa fitur ini berguna?
Misalnya kamu ingin membuat daftar nama:
var names = [
"Budi",
"Andi",
for (var i = 1; i <= 3; i++)
"User $i",
];
Hasil:
[Budi, Andi, User 1, User 2, User 3]
Ini sangat berguna di Flutter ketika membuat widget secara dinamis.
Misalnya:
Column(
children: [
Text("Judul"),
for (var i = 1; i <= 3; i++)
Text("Item $i"),
],
)
2. Spread Operator ...
Poin kedua adalah spread operator.
Bentuknya:
...
Fungsinya secara sederhana:
βMasukkan semua isi collection ini ke collection yang sedang kita buat.β
Misalnya:
var list1 = [10, 20, 30];
var list2 = [
15,
25,
35,
...list1,
];
print(list2);
Hasil:
[15, 25, 35, 10, 20, 30]
Perhatikan:
...list1
artinya bukan memasukkan list1 sebagai satu elemen.
Tanpa spread:
var list2 = [
15,
25,
35,
list1,
];
Hasilnya menjadi:
[15, 25, 35, [10, 20, 30]]
Artinya list1 menjadi List di dalam List.
Sedangkan dengan:
...list1
hasilnya:
[15, 25, 35, 10, 20, 30]
Analogi sederhana
Bayangkan kamu punya:
Kotak A:
[10, 20, 30]
Kalau kamu memasukkan kotak A ke kotak B:
[15, 25, 35, [10, 20, 30]]
Tapi kalau kamu bilang:
"Tuangkan semua isi kotak A ke kotak B"
hasilnya:
[15, 25, 35, 10, 20, 30]
Nah, ... melakukan hal kedua.
Spread bisa digunakan berkali-kali
Contoh video:
var list1 = [10, 20, 30];
var list2 = [15, 25, 35];
var list3 = [
100,
200,
...list1,
...list2,
];
print(list3);
Hasil:
[100, 200, 10, 20, 30, 15, 25, 35]
Urutannya tetap mengikuti posisi ...:
100
200
β
list1 β 10 20 30
β
list2 β 15 25 35
3. Index di luar batas menghasilkan RangeError
Ini sangat penting.
Misalnya:
var animals = [
"Cat",
"Dog",
"Bird",
"Fish",
];
Jumlah elemen:
4
Tetapi index dimulai dari 0.
Jadi:
Index Value
0 Cat
1 Dog
2 Bird
3 Fish
Index terakhir adalah:
3
Bukan 4.
Rumusnya:
last index = length - 1
Karena:
length = 4
4 - 1 = 3
Kalau kita melakukan ini?
print(animals[4]);
Dart akan menghasilkan:
RangeError
Karena index 4 tidak tersedia.
Secara sederhana:
[Cat, Dog, Bird, Fish]
β β β β
0 1 2 3
Tidak ada:
index 4
elementAt() juga sama
Misalnya:
print(animals.elementAt(4));
Hasilnya juga RangeError.
Jadi:
animals[4]
dan:
animals.elementAt(4)
sama-sama harus menggunakan index yang valid.
Cara aman
Sebelum mengakses:
if (index < animals.length) {
print(animals[index]);
}
Atau kalau tujuanmu hanya mengambil elemen berdasarkan kondisi tertentu, bisa gunakan pendekatan lain seperti firstWhere, elementAtOrNull dari package tertentu, atau pengecekan manual sesuai kebutuhan.
Intinya: jangan lupa bahwa index List dimulai dari 0.
4. for-in tidak mengubah elemen List secara langsung
Ini bagian yang sering membuat pemula bingung.
Misalnya:
var items = [10, 20, 30, 40, 50];
for (var item in items) {
item = item + 1;
}
print(items);
Mungkin kamu berpikir hasilnya:
[11, 21, 31, 41, 51]
Tetapi hasilnya tetap:
[10, 20, 30, 40, 50]
Kenapa?
Karena:
item
adalah variabel lokal yang menerima nilai elemen saat iterasi.
Bukan akses langsung ke posisi List.
Secara konsep:
List
β
10 β disalin/referenced ke variabel item
20 β disalin/referenced ke variabel item
30 β disalin/referenced ke variabel item
Ketika kamu melakukan:
item = item + 1;
yang berubah adalah variabel:
item
bukan:
items[index]
Contoh
var items = [10, 20, 30];
for (var item in items) {
item = item + 1;
print(item);
}
print(items);
Output:
11
21
31
[10, 20, 30]
Perhatikan:
Selama loop:
item β 11
item β 21
item β 31
Tetapi List asli tetap:
[10, 20, 30]
Lalu bagaimana kalau ingin benar-benar mengubah List?
Gunakan for biasa dengan index.
var items = [10, 20, 30];
for (var i = 0; i < items.length; i++) {
items[i] = items[i] + 1;
}
print(items);
Hasil:
[11, 21, 31]
Kenapa?
Karena sekarang kita benar-benar mengakses:
items[i]
Misalnya:
i = 0 β items[0] = 10 β menjadi 11
i = 1 β items[1] = 20 β menjadi 21
i = 2 β items[2] = 30 β menjadi 31
Perbandingan
| Loop | Bisa mendapatkan index? | Bisa mengubah list[index]? |
|---|---|---|
for-in | β tidak langsung | β tidak lewat variabel loop |
for biasa | β | β |
forEach | β tidak langsung | β variabel parameter bukan index |
Contoh forEach:
items.forEach((item) {
item = item + 1;
});
List asli juga tidak berubah.
Kapan menggunakan masing-masing?
Kalau hanya ingin membaca:
for (var item in items) {
print(item);
}
Bagus dan sederhana.
Kalau perlu index:
for (var i = 0; i < items.length; i++) {
print(items[i]);
}
Kalau ingin mengubah elemen:
for (var i = 0; i < items.length; i++) {
items[i] = items[i] + 1;
}
5. List adalah abstract class
Ini sedikit lebih advanced.
Di Dart, List merupakan abstract class.
Pertanyaannya:
Kalau
Listabstract, kenapa kita bisa melakukan ini?
var numbers = <int>[10, 20, 30];
atau:
var numbers = List<int>.empty();
Bukankah abstract class tidak bisa dibuat objeknya secara langsung?
Pertanyaan ini memang bagus.
Abstract class secara sederhana
Misalnya:
abstract class Animal {
void sound();
}
Kita tidak bisa:
var animal = Animal();
Karena Animal adalah abstract class.
Tetapi Dart memiliki mekanisme factory constructor.
Secara sederhana, video ingin menyampaikan:
List
β
β factory constructor
β
implementasi konkret List
Jadi ketika kamu menulis sesuatu seperti:
List<int>.empty(growable: true);
yang digunakan pada akhirnya adalah implementasi konkret dari List, bukan sekadar membuat instance langsung dari abstract class List.
Jadi jangan berpikir:
List abstract
β
List()
β
object langsung dari abstract List
Lebih tepat secara konsep:
List constructor
β
factory constructor
β
implementasi konkret
β
object List yang bisa digunakan
Ini salah satu alasan mengapa kamu bisa menggunakan constructor List meskipun List adalah abstract class.
6. List di dalam List
Nah, ini sangat penting ketika menangani data yang bentuknya seperti tabel.
Misalnya:
var matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
Perhatikan strukturnya.
List luar berisi tiga List:
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
Ini disebut:
List of List
Atau sering digunakan sebagai:
2D List / matrix
Gambarkan seperti tabel
column
0 1 2
ββββββββββ
row 0 β 1 2 3
row 1 β 4 5 6
row 2 β 7 8 9
Sekarang bagaimana mengambil angka 5?
Kita membutuhkan:
row = 1
column = 1
Kode:
print(matrix[1][1]);
Hasil:
5
Kenapa?
Pertama:
matrix[1]
mengambil:
[4, 5, 6]
Kemudian:
matrix[1][1]
mengambil index 1 dari List tersebut:
[4, 5, 6]
β
5
Mengambil angka 8
print(matrix[2][1]);
Hasil:
8
Karena:
matrix[2]
β
[7, 8, 9]
matrix[2][1]
β
8
Type-nya
Kita bisa menuliskan:
List<List<int>> matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
Bacanya:
Listyang setiap elemennya adalahList<int>.
Atau lebih mudah:
List
βββ List<int>
βββ List<int>
βββ List<int>
Bisa lebih dalam lagi
Secara teori:
List<List<List<int>>>
Ini berarti:
List
βββ List
βββ List<int>
Itulah mengapa collection di Dart sangat fleksibel.
7. Mengubah length List
Poin terakhir juga menarik.
Misalnya kita membuat List kosong:
var items = <int?>[];
Awalnya:
[]
Length:
0
Kemudian:
items.length = 5;
Sekarang:
[null, null, null, null, null]
Length menjadi:
5
Kenapa null?
Karena kita mengatakan:
“Saya ingin List ini memiliki 5 slot.”
Tetapi kita belum memberikan nilai sebenarnya.
Maka slot tersebut berisi:
null
Visualnya:
index
0 1 2 3 4
β β β β β
null null null null null
Kenapa saya menulis int??
Karena kita sedang menggunakan null safety.
Kalau:
List<int> items = [];
items.length = 5;
ini bermasalah secara konsep, karena int non-nullable tidak boleh berisi null.
Sedangkan:
List<int?> items = [];
berarti setiap elemen boleh berupa:
int
atau
null
Jadi:
List<int?> items = [];
items.length = 5;
print(items);
menghasilkan konsep:
[null, null, null, null, null]
Tapi ada hal penting tentang length
length bisa digunakan untuk memperbesar atau memperkecil List yang growable.
Misalnya:
var items = [10, 20, 30];
items.length = 5;
Hasil:
[10, 20, 30, null, null]
Sedangkan kalau:
items.length = 2;
maka elemen sisanya dipotong:
[10, 20]
Jadi:
length diperbesar
β
slot baru β null
length diperkecil
β
elemen di belakang β dibuang
Hati-hati ketika mengecilkan length, karena data yang terpotong hilang dari List tersebut.
Hubungan 7 fitur ini
Sekarang coba kita lihat semuanya sebagai satu konsep besar.
DART LIST
β
ββββββββββββββββββΌβββββββββββββββββ
β β β
β β β
Collection Spread Index
if / for ... RangeError
β β β
β β β
membuat isi menggabungkan akses elemen
List dinamis List lain berdasarkan index
Kemudian:
DART LIST
β
ββββββββββββββββββΌβββββββββββββββββ
β β β
β β β
Iterasi Abstract Nested List
β Class β
β β β
for / for-in factory List<List<int>>
β constructor β
β β
ubah data 2D List / Matrix
dengan index
Dan:
List.length
β
βββββββββ΄ββββββββ
β β
diperbesar diperkecil
β β
null baru elemen dibuang
Contoh gabungan
Sekarang kita gabungkan beberapa fitur sekaligus.
var numbers = [
10,
20,
if (5 > 2)
30,
for (var i = 1; i <= 3; i++)
i,
];
var extra = [100, 200];
var result = [
...numbers,
...extra,
];
print(result);
Mari kita proses.
Langkah 1
10,
20,
Hasil sementara:
[10, 20]
Langkah 2
if (5 > 2)
30,
Karena:
5 > 2 = true
menjadi:
[10, 20, 30]
Langkah 3
for (var i = 1; i <= 3; i++)
i,
menambahkan:
1, 2, 3
sehingga:
[10, 20, 30, 1, 2, 3]
Langkah 4
...numbers
semua isi numbers dimasukkan.
Langkah 5
...extra
semua isi extra juga dimasukkan.
Hasil:
[10, 20, 30, 1, 2, 3, 100, 200]
β οΈ Beberapa hal dari video yang perlu diluruskan
Ada beberapa bagian transcript yang merupakan penyederhanaan untuk pemula.
1. for-in bukan berarti List “tidak bisa dimodifikasi”
Yang benar:
for (var item in items) {
item = item + 1;
}
tidak mengubah elemen List karena item adalah variabel iterasi.
Kalau kita melakukan:
for (var i = 0; i < items.length; i++) {
items[i] += 1;
}
List memang berubah.
Jadi masalahnya bukan:
“
for-intidak boleh mengubah List.”
Tetapi:
Mengubah variabel loop tidak otomatis mengubah posisi elemen di List.
2. List kosong + length dan null safety perlu diperhatikan
Video mengatakan List bisa menjadi:
[null, null, null, null, null]
Konsep tersebut benar untuk slot yang belum memiliki nilai, tetapi dalam Dart modern dengan sound null safety, tipe List harus mengizinkan null.
Contohnya:
var items = <int?>[];
items.length = 5;
bukan:
var items = <int>[];
karena int tidak menerima null.
3. List abstract class
Jangan terlalu fokus dulu pada mekanisme internal factory constructor kalau kamu belum belajar OOP.
Untuk sekarang cukup ingat:
Listadalah abstract class, dan constructor List dapat menggunakan factory untuk menghasilkan implementasi konkret yang sebenarnya digunakan.
Nanti ketika belajar:
- abstract class
- interface
- factory constructor
- implements
konsep ini akan jauh lebih mudah dipahami.
π§ Inti yang harus kamu ingat
Kalau mau menghafal video ini, cukup pegang 7 hal berikut:
1. Collection if
var list = [
10,
if (true) 20,
];
20 hanya masuk kalau kondisi true.
2. Collection for
var list = [
for (var i = 1; i <= 3; i++)
i,
];
Hasil:
[1, 2, 3]
3. Spread ...
var a = [1, 2, 3];
var b = [
10,
...a,
];
Hasil:
[10, 1, 2, 3]
4. Index dimulai dari 0
[10, 20, 30, 40]
β β β β
0 1 2 3
Jadi:
list[4]
β RangeError.
5. for-in vs for
for (var item in list) {
item = item + 1;
}
Tidak mengubah elemen List.
Untuk mengubah:
for (var i = 0; i < list.length; i++) {
list[i] += 1;
}
6. List bisa berisi List
var matrix = [
[1, 2],
[3, 4],
];
Ambil 4:
matrix[1][1]
7. length bisa mengubah jumlah slot
var items = <int?>[];
items.length = 5;
Hasil:
[null, null, null, null, null]
Cheat sheet
// Collection if
var a = [
10,
if (true) 20,
];
// Collection for
var b = [
for (var i = 1; i <= 5; i++)
i,
];
// Spread
var c = [
...a,
...b,
];
// Access
print(c[0]);
// Modify dengan index
for (var i = 0; i < c.length; i++) {
c[i] = c[i] + 1;
}
// Nested List / 2D List
var matrix = [
[1, 2, 3],
[4, 5, 6],
];
print(matrix[1][2]); // 6
// Mengubah length
var empty = <int?>[];
empty.length = 5;
print(empty);
// [null, null, null, null, null]
Kalau disederhanakan menjadi satu kalimat: List di Dart bukan cuma tempat menyimpan banyak nilai, tetapi juga bisa dibangun secara dinamis dengan if/for, digabung dengan ..., diakses berdasarkan index, dibuat bertingkat menjadi matrix, dan ukurannya dapat diubah.