Day 6: Advanced Collections
Build dynamic, real-world data structures using collection if, spread operators, sets, and maps to power every list and grid in your Flutter apps.
မင်္ဂလာပါ.. 👋
100 days of Flutter ရဲ့ Day 6 က ကြိုဆိုပါတယ်။ ဒီနေ့မှာတော့ dart langauge နဲ့ ပတ်သက်တာတွေကို ဆက်လက်ပြီး လေ့လာသွားပါမယ်။ ဒီနေ့ဆွေးနွေးသွားမယ့် ခေါင်းစဥ်တွေကတော့
- What are Collections?
- Spread Operator
- Collection if
- Collection for
တွေပဲ ဖြစ်ပါတယ်။
What are Collections?
Collection တွေဆိုတာကတော့ သက်ဆိုင်ရာ value တွေကို တခုတစည်းထဲ စုစည်းထားတာမျိုးပဲ ဖြစ်ပါတယ်။ Facebook post တွေ၊ WhatsApp message တွေ၊ Amazon products တွေ စသဖြင့် data တွေကို ကိုင်တွယ်တဲ့အခါ collection တွေက မရှိမဖြစ်ပါ။ ဒီတော့ Dart language မှာ collection တွေ တည်ဆောက်ဖို့ ပေးထားတဲ့ List, Set, Map တွေကို လေ့လာကြည့်ရအောင်ပါ။
List
ဒါကိုတော့ app တွေရေးတဲ့အခါ အများဆုံး မြင်ရမှာပါ။ List ကိုတော့ ordered collection ဆိုပြီး ခေါ်ပါတယ်။ သူ့ကို သတ်မှတ်တဲ့အခါ [] ကို အသုံးပြုပါတယ်။ အစီအစဥ်အလိုက် (order) သတ်မှတ်ထားတာ ဖြစ်တဲ့အတွက် သူ့ထဲက value တွေကို နေရာ (index) အလိုက် ခေါ်သွားလို့ရပါတယ်။
void main() {
List<String> fruits = ['Apple', 'Banana', 'Orange', 'Mango'];
print(fruits); // [Apple, Banana, Orange, Mango]
print(fruits[0]); // Apple (first item, index 0)
print(fruits[2]); // Orange (third item, index 2)
print(fruits.length); // 4 (total items)
// Lists maintain ORDER
print(fruits.first); // Apple
print(fruits.last); // Mango
// Lists ALLOW duplicates
fruits.add('Apple'); // Adding duplicate
print(fruits); // [Apple, Banana, Orange, Mango, Apple]
fruits.remove('Apple'); // Removing first occurance
print(fruits); // [Banana, Orange, Mango, Apple]
fruits.insert(0, 'Berry'); // Adding new at specific place (shift values)
print(fruits); // [Berry, Banana, Orange, Mango, Apple]
fruits.clear(); // Removing all
print(fruits); // []
}
အပေါ်မှာ ပြထားတဲ့ code ထဲမှာ ကြည့်မယ်ဆို List နဲ့ ပတ်သက်တဲ့ အသုံးပြုတဲ့ ပုံစံတွေကို တွေ့ရမှာပါ။ အရင်ဆုံး list တခုကို သတ်မှတ်တော့မယ်ဆို ဘယ်လို data type တွေ ထည့်ထားမှာလဲဆိုတာ သတ်မှတ်ပေးရပါတယ်။ Ordered (အစီအစဥ်တကျ) ဖြစ်တဲ့အတွက် list ရဲ့ .first .last ဆိုတဲ့ အသုံးတွေနဲ့ ပထမဆုံးနောက်ဆုံး value တွေကို ရယူနိုင်ပါတယ်။ တကယ်လို့ အခြားနေရာက value တွေကို ရယူချင်တယ်ဆိုရင်တော့ သူတို့နဲ့ဆိုင်တဲ့ index တွေ (0, 1, 2,...) စသဖြင့် သုံးပြီးတော့ ရယူနိုင်ပါတယ်။ value အသစ်ထည့်ချင်တယ်ဆိုရင် .add(...) ဆိုတဲ့ function ကို ခေါ်ပြီးတော့ အသစ်ထည့်နိုင်ပါတယ်။ ထည့်တဲ့အခါ ရှိပြီးသား value ကို ထပ်ထည့်လို့လဲ ရပါတယ်။ duplicate အနေနဲ့ ထပ်ပြီး ဝင်သွားမှာပါ။ list ထဲက value ကို ဖျက်ချင်တယ်ဆိုလဲ .remove(...) ဆိုတဲ့ function နဲ့ ဖျက်လို့ရပါတယ်။ value အသစ်ကို ကိုယ်ထည့်ချင်တဲ့နေရာမှာ ထည့်မယ်ဆို .insert(index, ...) ဆိုတဲ့ function နဲ့ ထည့်လို့ရပါတယ်။ နောက်ဆုံး list ထဲက value အကုန်ကို ဖျက်ချင်တယ်ဆိုရင်တော့ .clear() ဆိုတဲ့ function နဲ့ ဖျက်လို့ရပါတယ်။ ဒါကတော့ list နဲ့ ပတ်သက်တဲ့ အခြေခံအသုံးတွေပဲ ဖြစ်ပါတယ်။
List ထဲကို value မတူတာတွေ ထည့်ချင်တဲ့အခါdynamic,Objectဆိုတဲ့ type တွေသတ်မှတ်ပြီး ထည့်သွားလို့ရပါတယ်။ ဒီလိုအသုံးပြုတဲ့အခါ type safety မရှိတော့တဲ့အတွက် type check တွေတော့ လုပ်သွားပေးဖို့ လိုပါလိမ့်မယ်။
Set
Set ဆိုတာကလဲ value တွေကို စုထားတဲ့ဟာပဲဖြစ်ပါတယ်။ သူ့ကိုတော့ ထပ်နေတဲ့ value တွေ မလိုချင်တဲ့အခါ အသုံးပြုပါတယ်။ သူ့ထဲမှာ unique ဖြစ်တဲ့ value တွေကိုပဲ ထည့်လို့ရတာ ဖြစ်ပြီး သတ်မှတ်တဲ့အခါ {} ကို အသုံးပြုပါတယ်။
void main() {
Set<int> userIds = {101, 102, 103, 101, 102};
print(userIds); // {101, 102, 103}
userIds.add(104); // Works
userIds.add(101); // Ignored! Already exists
print(userIds); // {101, 102, 103, 104}
print(userIds.contains(101)); // true
print(userIds.contains(105)); // false
userIds.remove(101);
print(userIds); // {102, 103, 104}
userIds.clear();
print(userIds); // {}
}
Set မှာလဲ list လိုပဲ ဘယ်လို value တွေ ထည့်မှာလဲဆိုတဲ့ data type သတ်မှတ်ပေးဖို့ လိုအပ်ပါတယ်။ List လိုမျိုးပဲ သူ့မှာလဲ value တွေထည့်ဖို့အတွက် .add(...) ဆိုတဲ့ function ရှိပါတယ်။ ဖျက်ဖို့အတွက် .remove(...) ကို သုံးနိုင်ပြီးတော့ အကုန် ဖျက်ချင်တဲ့အခါ .clear() ဆိုတာကို သုံးနိုင်ပါတယ်။
void main() {
List<int> userIdsList = [101, 102, 103, 101, 102];
print(userIdsList); // [101, 102, 103, 101, 102]
var uniqueIds = userIdsList.toSet();
print(uniqueIds); // {101, 102, 103}
}တကယ်လို့ List ကနေ unique value တွေကို လိုချင်တယ်ဆို တခုချင်း လိုက်စစ်မနေဘဲ Set ကိုပြောင်းပြီးတော့ unique value တွေကို အပေါ်မှာ ပြထားသလိုပဲ ရယူလို့ရပါတယ်။ Set ကတော့ ordered collection မဟုတ်တဲ့အတွက် သူ့ထဲက value တွေ အစီအစဥ်တကျ အမြဲ ဖြစ်နေမှာမဟုတ်ပါဘူး။ ဒါပေမယ့် unique value တွေကို သိမ်းပေးပြီး ရှာတာ (lookup) တော့ list ထပ်ပိုပြီး မြန်ပါတယ်။
Map
Map ကတော့ List နဲ့ Set လိုမျိုး value တခုထဲကို သိမ်းထားတာ မဟုတ်ဘဲ key, value ဆိုပြီး အတွဲလိုက် သိမ််းထားပေးတာမျိုး ဖြစ်ပါတယ်။ သူ့ထဲကို တခုခု ထည့်သိမ်းချင်ပြီဆို ထည့်သိမ်းမယ့် value အတွက် နာမည် ပေးရတာမျိုး ဖြစ်ပါတယ်။
void main() {
Map<String, dynamic> user = {
'name': 'Aung Aung',
'age': 28,
'email': 'aung@example.com',
'isPremium': true,
'country': 'Myanmar',
};
print(user['name']); // Aung Aung
print(user['email']); // aung@example.com
print(user['isPremium']); // true
print(user['nonExistingKey']); // null
user['phone'] = '09-123-456'; // adding new key,value
user['age'] = 29; // updating value
print(user);
print(user.containsKey('name')); // true
print(user.containsKey('address')); // false
}အပေါ်မှာ ပြထားသလိုပဲ Map ကို သတ်မှတ်တဲ့အခါမှာလဲ data type သတ်မှတ်ပေးရပါတယ်။ Map မှာတော့ key, value ဆိုပြီး ၂ခုတွဲ ရှိတဲ့အတွက် data type ကို ၂ခုလုံးအတွက် သတ်မှတ်ပေးရပါတယ်။ အပေါ်မှာ key အတွက် String ဆိုပြီး သတ်မှတ်ပေးထားပေမယ့် value အတွက် dynamic ဆိုပြီး သတ်မှတ်ပေးထားတာကို တွေ့ရမှာပါ။ ဒါကတော့ value နေရာမှာ data type မျိုးစုံး (String, int, boolean, etc) သတ်မှတ်နိုင်ဖို့ အတွက် ဖြစ်ပါတယ်။ တကယ်လို့ ကိုယ်ထည့်သွားမယ့် value တွေက type တခုထဲသေချာတယ်ဆို အဲ့ဒီ type ကို သတ်မှတ်ထားပေးလို့ရပါတယ်။
Map ထဲက value တွေကို ပြန်လိုချင်တဲ့အခါမှာတော့ index နဲ့မဟုတ်ဘဲ key နဲ့ ပြန်ပြီး ဆွဲထုတ်ရပါတယ်။ တကယ်လို့ key က Map ထဲမှာ ရှိမနေဘူးဆို null ကို ပြန်ပေးမှာပဲ ဖြစ်ပါတယ်။ Map ထဲကို value အသစ်တွေ ထည့်ချင်တဲ့အခါ key အသစ် သတ်မှတ်ပြီး ထည့်ပေးလို့ရပါတယ်။ တကယ်လို့ ရှိပြီးသား key ဖြစ်နေတယ်ဆိုရင်တော့ ရှိနေတဲ့ value ကို ပြောင်းပေးသွားမှာ ဖြစ်ပါတယ်။
Spread Operator
ဆက်ပြီးတော့ speread operator ဆိုတာဘဲလဲ ကြည့်ကြည့်ရအောင်ပါ။ Javascript, Typescript သုံးဖူးတဲ့သူတွေဆိုရင်တော့ ဒါကို သိပ်ပြီး စိမ်းမယ် မထင်ပါဘူး။ သူ့ကိုတော့ collection ထဲက value တွေကို ဖြန့်ချချင်တဲ့အခါ အသုံးပြုပါတယ်။
void main() {
var fruits = ['Apple', 'Banana'];
var vegetables = ['Carrot', 'Broccoli'];
var groceries1 = [fruits, vegetables];
print(groceries1); // [[Apple, Banana], [Carrot, Broccoli]]
var groceries2 = [...fruits, ...vegetables];
print(groceries2); // [Apple, Banana, Carrot, Broccoli]
}List တွေကို သတ်မှတ်ပြီး value တွေတခါထဲ ထည့်တာဖြစ်တဲ့အတွက် List<String> အစား var ကိုလဲ အသုံးပြုလို့ရပါတယ်။ dart က value တွေကို reference လုပ်ပြီး data type ကို auto သတ်မှတ်ပေးသွားမှာပါ။ တကယ်လို့ declaration နဲ့ assignment က သပ်သပ်ပြီး ဖြစ်နေတယ်ဆိုရင်တော့ data type သတ်မှတ်ပေးဖို့ လိုအပ်ပါတယ်။
အပေါ်မှာတော့ List ၂ခုကို ၁ခုထဲအဖြစ် ပေါင်းတာကို ပြထားပေးပါတယ်။ ပေါင်းတဲ့အချိန်မှာ တကယ်လို့ spread operator (...) ကို အသုံးမပြုဘူးဆို nested list ဖြစ်သွားမှာပါ။
void main() {
var venue1 = {"Football", "Basketball"};
var venue2 = {"Football", "Baseball"};
var allSports1 = {venue1, venue2};
print(allSports1); // {{Football, Basketball}, {Football, Baseball}}
var allSports2 = {...venue1, ...venue2};
print(allSports2); // {Football, Basketball, Baseball}
}void main() {
var partialInfo1 = {'name': 'Aung Aung', 'age': 28};
var partialInfo2 = {
'email': 'aung@aung.com',
'country': 'Myanmar',
'age': 29,
};
var fullInfo1 = {partialInfo1, partialInfo2};
print(
fullInfo1,
); // {{name: Aung Aung, age: 28}, {email: aung@aung.com, country: Myanmar, age: 29}}
var fullInfo2 = {...partialInfo1, ...partialInfo2};
print(
fullInfo2,
); // {name: Aung Aung, age: 29, email: aung@aung.com, country: Myanmar}
}
Set နဲ့ Map အတွက်လဲ spread operator ရဲ့ အလုပ်လုပ်ပုံက ဆင်တူပါတယ်။ အပေါ်က code တွေကို ကြည့်ရင် ရှင်းလင်းသွားမယ်လို့ ထင်ပါတယ်။
Nullable Collection
Spread operator ကို အသုံးပြုတဲ့အခါ တကယ်လို့ collection က nullable ဖြစ်နေရင် အခုလိုမျိုး ...? ဆိုပြီးတော့ spread operator နောက်မှာ question mark ကို ထည့်ပြီးတော့ ရေးလို့ရပါတယ်။ value က null မဖြစ်တော့မှ collection ကို speread လုပ်ပေးသွားမှာ ဖြစ်ပါတယ်။
void main() {
var featuredProducts = ['Product A', 'Product B'];
var regularProducts = ['Product C', 'Product D', 'Product E'];
List<String>? vipProducts; // Only exists for VIP users
var catalog = [
'New Arrivals Header',
...featuredProducts,
'Regular Products Header',
...regularProducts,
...?vipProducts, // Safe even if null
'Footer',
];
print(catalog);
}
// Output:
// [New Arrivals Header, Product A, Product B, Regular Products Header, Product C, Product D, Product E, Footer]
Collection If
Collection if ဆိုတာကတော့ condition ပေါ်မူတည်ပြီး collection ထဲကို value တွေ ထည့်သွားတာကို ပြောတာပဲ ဖြစ်ပါတယ်။
void main() {
bool isAdmin = true;
bool isPremium = false;
List<String> menu = [];
menu.add('Home');
menu.add('Profile');
if (isAdmin) {
menu.add('Admin Panel');
}
if (isPremium) {
menu.add('Premium Dashboard');
}
menu.add('Settings');
print(menu);
}
// Output: [Home, Profile, Admin Panel, Settings]အပေါ်မှာ ပြထားတဲ့ code ကိုကြည့်မယ်ဆို menu ထဲက တချို့ value တွေက condition ပေါ်မူတည်ပြီး ထည့်ပေးထားတာကို တွေ့ရမှာပါ။ ပြထားတဲ့ code မှာ error ဆိုပြီးတော့ ရှိမနေပါဘူး။ အပေါ်က result ကိုပဲ တိုတိုနဲ့ အောက်မှာ ပြထားတဲ့အတိုင်း ရေးလို့ရပါတယ်။
void main() {
bool isAdmin = true;
bool isPremium = false;
var menu = [
'Home',
'Profile',
if (isAdmin) 'Admin Panel',
if (isPremium) 'Premium Dashboard',
'Settings',
];
print(menu);
}
// Output: [Home, Profile, Admin Panel, Settings]အခုလို ရေးလိုက်ခြင်းအားဖြင့် အများကြီးတိုပြီး ရှင်းလင်းသွားတာကို တွေ့နိုင်ပါတယ်။ if check ဖြစ်တဲ့အတွက် ပိုပြီး complex ဖြစ်တဲ့ condition တွေကိုလဲ ထည့်ပြီး စစ်နိုင်ပါတယ်။
Collection for
Collection if ဆိုတာကတော့ for loop logic နဲ့ collection ထဲကို value တွေ ထည့်သွားတာကို ပြောတာပဲ ဖြစ်ပါတယ်။
void main() {
List<String> menuItems = [];
menuItems.add('Dashboard');
for (var i = 1; i <= 5; i++) {
menuItems.add('Module $i');
}
menuItems.add('Settings');
print(menuItems);
}
// Output: [Dashboard, Module 1, Module 2, Module 3, Module 4, Module 5, Settings]အပေါ်မှာ ပြထားတဲ့ code မှာဆိုရင် loop ပတ်ပြီးတော့ menuItems list ထဲကို value တွေ ထည့်သွားတာကို တွေ့ရမှာ ဖြစ်ပါတယ်။ ဒါကို ပိုပြီး တိုတိုရှင်းရှင်းဖြစ်အောင် အခုလို ရေးလို့ရပါတယ်။
void main() {
var menuItems = [
'Dashboard',
for (var i = 1; i <= 5; i++) 'Module $i',
'Settings',
];
print(menuItems);
}
// Output: [Dashboard, Module 1, Module 2, Module 3, Module 4, Module 5, Settings]Example
void main() {
// ============================================
// SETUP DATA
// ============================================
bool isLoggedIn = true;
bool isPremiumUser = false;
bool hasActivePromo = true;
// Core products always shown
var featuredProducts = ['iPhone 15', 'MacBook Pro'];
var regularProducts = ['AirPods', 'Magic Mouse', 'iPad'];
// Premium products - only for premium users (might be null)
List<String>? premiumProducts = isPremiumUser
? ['Pro Display XDR', 'Mac Studio']
: null;
// Sale items - might not exist
List<String>? saleItems = hasActivePromo
? ['iPhone 14 (Sale!)', 'Apple Watch (Sale!)']
: null;
var categories = ['Electronics', 'Accessories', 'Computers'];
// ============================================
// BUILD CATALOG USING ALL OPERATORS
// ============================================
var productCatalog = [
// Static header
'🏪 APPLE STORE',
'─────────────',
'',
// SPREAD OPERATOR - Merge featured products
'⭐ FEATURED:',
...featuredProducts,
'',
// COLLECTION IF - Show sale section only if active
if (hasActivePromo) '🔥 FLASH SALE:',
// NULL-AWARE SPREAD - Safe even if null
...?saleItems,
if (hasActivePromo) '', // Empty line after sale
// Regular products section
'📦 PRODUCTS:',
...regularProducts,
'',
// COLLECTION FOR - Generate category sections
for (var category in categories) '📂 ${category} Department',
'',
// COLLECTION IF + SPREAD - Premium section (conditional)
if (isPremiumUser) '💎 PREMIUM EXCLUSIVE:',
...?premiumProducts, // Safe even when null
if (isPremiumUser) '',
// COLLECTION FOR + IF - Generate numbered recommendations
'🎁 RECOMMENDED FOR YOU:',
for (var i = 1; i <= 5; i++)
if (isLoggedIn || i <= 2) 'Recommendation #$i',
'',
// Footer
'─────────────',
if (isLoggedIn) '👤 Logged in as User',
if (!isLoggedIn) '🔐 Login for personalized recommendations',
];
// ============================================
// DISPLAY THE CATALOG
// ============================================
print('=== PRODUCT CATALOG ===\n');
for (var item in productCatalog) {
print(item);
}
print('\n=== CATALOG DETAILS ===');
print('Total items in catalog: ${productCatalog.length}');
print('Has sale items: $hasActivePromo');
print('Premium access: $isPremiumUser');
print('User logged in: $isLoggedIn');
}=== PRODUCT CATALOG ===
🏪 APPLE STORE
─────────────
⭐ FEATURED:
iPhone 15
MacBook Pro
🔥 FLASH SALE:
iPhone 14 (Sale!)
Apple Watch (Sale!)
📦 PRODUCTS:
AirPods
Magic Mouse
iPad
📂 Electronics Department
📂 Accessories Department
📂 Computers Department
🎁 RECOMMENDED FOR YOU:
Recommendation #1
Recommendation #2
Recommendation #3
Recommendation #4
Recommendation #5
─────────────
👤 Logged in as User
=== CATALOG DETAILS ===
Total items in catalog: 29
Has sale items: true
Premium access: false
User logged in: trueဒီနေ့ Day 6 အတွက်ကတော့ ဒီလောက်ပဲ ဖြစ်ပါတယ်။ အဆုံးထိ ဖတ်ပေးတဲ့အတွက် အများကြီး ကျေးဇူးတင်ပါတယ်။ နားမလည်တာတွေ အဆင်မပြေတာတွေ ရှိခဲ့ရင်လဲ အောက်မှာပေးထားတဲ့ discord server ထဲမှာ လာရောက်ဆွေးနွေးနိုင်ပါတယ်။ နောက်နေ့တွေမှာလဲ ဆက်လက်ပြီး sharing လုပ်သွားပေးသွားမှာ ဖြစ်တဲ့အတွက် subscribe လုပ်ထားဖို့ ဖိတ်ခေါ်ပါတယ်။
- Youtube: https://www.youtube.com/@arkarmintun
- Newsletter: https://arkar.dev/
- Discord: https://discord.gg/3xUJ6k6dkH