Advanced Data Structures (Set, Map, WeakSet, WeakMap)

"Performance & Memory Management Mastery"

একজন জুনিয়র ডেভেলপার শুধু Array আর Object চেনে। কিন্তু একজন সিনিয়র ডেভেলপার জানে কখন অ্যাপের পারফরম্যান্স বাড়ানোর জন্য Set বা Map ব্যবহার করতে হয় এবং মেমোরি লিক ঠেকানোর জন্য WeakMap ব্যবহার করতে হয়।

এই অধ্যায়ে আমরা জাভাস্ক্রিপ্টের এই ৪টি পাওয়ারফুল ডাটা স্ট্রাকচার শিখব।

⭐ ১. কেন আমাদের Set/Map/WeakSet/WeakMap দরকার?

আমাদের তো Array আর Object ছিলই, তাহলে এগুলো কেন?

Array: ডুপ্লিকেট ভ্যালু আটকানো কঠিন (লুপ চালিয়ে চেক করতে হয়)

Object Keys: অবজেক্টের Key সবসময় স্ট্রিং বা সিম্বল হতে হয়। তুমি চাইলেই একটা অবজেক্টকে বা ফাংশনকে Key বানাতে পারবে না

Performance: অনেক বড় ডেটাসেটে অবজেক্ট বা অ্যারে স্লো কাজ করে (Searching O(n))

Memory Leak: অবজেক্ট স্ট্রং রেফারেন্স ধরে রাখে, ফলে অপ্রয়োজনীয় ডেটা মেমোরি থেকে রিমুভ হয় না

এই সমস্যাগুলো সমাধান করতেই ES6-এ এই নতুন স্ট্রাকচারগুলো এসেছে।

⭐ ২. SET — ইউনিক ভ্যালুর কালেকশন

Set হলো এমন একটি ঝুড়ি যেখানে তুমি ডুপ্লিকেট কিছু রাখতে পারবে না। সব ভ্যালু ইউনিক হতে হবে।

✅ বৈশিষ্ট্য:

  • শুধুমাত্র ইউনিক আইটেম স্টোর করে
  • লুকআপ বা খোঁজার গতি সুপার ফাস্ট O(1)
  • ইনডেক্স দিয়ে এক্সেস করা যায় না (set[0] কাজ করে না)

💻 কোড উদাহরণ:

// ১. সেট তৈরি করা (ডুপ্লিকেটগুলো অটোমেটিক বাদ পড়ে যাবে)
const s = new Set([1, 2, 3, 3, 4]);
console.log(s); // Output: Set { 1, 2, 3, 4 }

// ২. নতুন আইটেম যোগ করা
s.add(5);
s.add(5); // এটা ইগনোর করবে, কারণ ৫ আগেই আছে

// ৩. চেক করা (সবচেয়ে ফাস্ট মেথড)
console.log(s.has(3)); // true

// ৪. ডিলিট করা
s.delete(2);

// ৫. সাইজ দেখা
console.log(s.size); // 4

// ৬. লুপ চালানো
for (let x of s) {
    console.log(x);
}

// ৭. সেট থেকে অ্যারেতে কনভার্ট করা
const arr = [...s];

🔥 Real Use Cases of Set

১. ডুপ্লিকেট রিমুভ করা (সবচেয়ে জনপ্রিয় ব্যবহার):

const numbers = [10, 20, 10, 30, 20];
const unique = [...new Set(numbers)]; 
console.log(unique); // [10, 20, 30]

২. ফাস্ট মেম্বারশিপ চেক (O(1)):

if (visitedIds.has(currentId)) {
    // Already visited
}

⭐ ৩. MAP — অবজেক্টের বড় ভাই (Better Object)

Map দেখতে অবজেক্টের মতোই (Key-Value Pair), কিন্তু এটি অনেক বেশি শক্তিশালী।

✅ পার্থক্যটা কোথায়?

  • Any Key: অবজেক্টে কী (Key) শুধু স্ট্রিং হয়। ম্যাপে কী (Key) যেকোনো কিছু হতে পারে (Object, Array, Function)
  • Order: ম্যাপ ইনসার্ট করার অর্ডার মনে রাখে
  • Size: map.size দিয়ে সহজেই সাইজ পাওয়া যায় (অবজেক্টে লুপ চালাতে হয়)

💻 কোড উদাহরণ:

const m = new Map();

// যেকোনো টাইপের ডাটা Key হতে পারে
const userObj = { id: 1 };

m.set("name", "Shagor");       // String Key
m.set(userObj, "User Details"); // Object Key! 🔥
m.set(100, "Number Key");      // Number Key

// ভ্যালু পাওয়া
console.log(m.get("name"));   // "Shagor"
console.log(m.get(userObj));  // "User Details"

// চেক করা
console.log(m.has("name")); // true

// ডিলিট করা
m.delete("name");

// লুপ চালানো
for (let [key, value] of m) {
    console.log(key, value);
}

📊 Map vs Object (Comparison)

FeatureObject {}Map new Map()
Key TypesString / SymbolAny Type ✅
Orderগ্যারান্টি দেয় নাইনসারশন অর্ডার ঠিক রাখে ✅
Sizeম্যানুয়ালিmap.size বিল্ট-ইন ✅
Performanceছোট ডেটার জন্যবড় ডেটা এবং ফ্রিকুয়েন্ট আপডেটে ফাস্ট 🚀

🔥 Real Use Cases of Map

১. API রেসপন্স ক্যাশ করা:

const cache = new Map();

function getUser(id) {
    if (cache.has(id)) return cache.get(id);
    const user = fetchUser(id);
    cache.set(id, user);
    return user;
}

২. কোনো কিছু কতবার আছে তা গণনা করা:

const counter = new Map();
const fruits = ["apple", "banana", "apple"];

for (let f of fruits) {
    counter.set(f, (counter.get(f) || 0) + 1);
}
console.log(counter.get("apple")); // 2

⭐ ৪. WEAKSET — মেমোরি সেভার (Weak References)

WeakSet ঠিক Set এর মতোই, কিন্তু এর দুটি বড় পার্থক্য আছে:

  • এটি শুধুমাত্র Object স্টোর করতে পারে (Number/String না)
  • এটি Weak Reference রাখে। অর্থাৎ, যদি ওই অবজেক্টটি অন্য কোথাও ব্যবহৃত না হয়, তবে Garbage Collector অটোমেটিক্যালি সেটা ডিলিট করে দেয়

💻 কোড উদাহরণ:

let user = { name: "Shagor" };
const ws = new WeakSet();

ws.add(user);
console.log(ws.has(user)); // true

user = null; // ইউজারকে নাল করে দিলাম

// কিছুক্ষণ পর জাভাস্ক্রিপ্ট অটোমেটিক 'ws' থেকেও ইউজারকে ডিলিট করে দেবে।
// মেমোরি লিক হবে না।

🔥 Use Case:

DOM Element Tracking: কোন এলিমেন্ট ভিজিট করা হয়েছে তা ট্র্যাক করা। যদি এলিমেন্ট রিমুভ হয়, WeakSet থেকেও মুছে যাবে।

⭐ ৫. WEAKMAP — প্রাইভেট এবং সেফ স্টোরেজ

এটি Map এর মতোই, কিন্তু এর Key অবশ্যই Object হতে হবে। এবং এটিও অটোমেটিক গার্বেজ কালেকশন সাপোর্ট করে।

💻 কোড উদাহরণ:

let product = { id: 101 };
const wm = new WeakMap();

wm.set(product, "Secret Info");
console.log(wm.get(product)); // "Secret Info"

product = null; 
// product মেমোরি থেকে মুছে গেলে, 'Secret Info' ও wm থেকে গায়েব হয়ে যাবে।

⭐ ৬. কেন WeakMap/WeakSet বানানো হয়েছে? (Deep Logic)

সাধারণ Map বা Object ডাটাকে শক্তভাবে (Strongly) ধরে রাখে।

ধরো তুমি Map এর ভেতরে একটা বড় অবজেক্ট রেখেছ। তুমি যদি সেই অবজেক্টটা ডিলিটও করে দাও, Map তাকে ছাড়বে না। ফলে মেমোরি ফুল হতে থাকবে (Memory Leak)।

WeakMap এবং WeakSet ডাটাকে হালকাভাবে (Weakly) ধরে রাখে। মেইন অবজেক্ট ডিলিট হলে এরাও ডেটা ছেড়ে দেয়। বড় অ্যাপ্লিকেশনে (যেমন React, Node.js Server) মেমোরি বাঁচাতে এটি অপরিহার্য।

⭐ ৭. Real-World Use Cases (Senior Level)

কেস ১: ক্লাসের মধ্যে প্রাইভেট ডেটা রাখা

const privateData = new WeakMap();

class User {
    constructor(name) {
        privateData.set(this, { name });
    }
    getName() {
        return privateData.get(this).name;
    }
}

কেস ২: DOM এলিমেন্ট ট্র্যাক করা (Memory Leak ছাড়া)

const clickedElements = new WeakSet();

function clickHandler(el) {
    if (!clickedElements.has(el)) {
        clickedElements.add(el);
        console.log("First time clicked!");
    }
}

কেস ৩: হেভি ক্যালকুলেশন ক্যাশ করা

const cache = new WeakMap();

function heavyCompute(obj) {
    if (cache.has(obj)) return cache.get(obj);
    const result = obj.value * 10000;
    cache.set(obj, result);
    return result;
}

⭐ ৮. Performance Comparison (Big O Notation)

Set vs Array

OperationArraySetকেন Set ভালো?
LookupO(n)O(1)অ্যারে লুপ চালায়, সেট ডাইরেক্ট ধরে
InsertO(1)O(1)দুটোই সমান ফাস্ট
DeleteO(n)O(1)অ্যারেতে ইনডেক্স শিফট করতে হয়, সেটে লাগে না

Map vs Object

OperationObjectMap
LookupO(1)O(1)
Key TypesLimitedUnlimited ✅
IterationSlowFast ✅

⭐ ৯. Senior Pitfalls (সাবধানতা) ⚠️

  • ❌ WeakMap এবং WeakSet এর ওপর লুপ চালানো যায় না (forEach, for...of কাজ করে না)
  • ❌ এদের size প্রপার্টি নেই। কয়টা আইটেম আছে তা গোনা যায় না
  • ❌ কনসোলে এদের ভেতরের ডেটা সবসময় দেখা যায় না (কারণ ব্রাউজার কখন ক্লিন করবে তা ঠিক নেই)
  • ❌ পার্মানেন্ট ডেটার জন্য WeakMap ব্যবহার করবে না, টেম্পোরারি বা ক্যাশিংয়ের জন্য ব্যবহার করবে

⭐ ১০. Real Interview Questions

Q1: Array এর বদলে Set কেন ব্যবহার করব?

উত্তর: যখন ইউনিক ভ্যালু দরকার এবং ফাস্ট সার্চিং (O(1)) দরকার।

Q2: Map এবং Object এর মধ্যে কোনটা বেটার?

উত্তর: যদি ডেটা ফ্রিকুয়েন্টলি অ্যাড/রিমুভ করতে হয় এবং কী (Key) হিসেবে অবজেক্ট দরকার হয়, তবে Map বেটার। ছোট এবং স্ট্যাটিক ডেটার জন্য Object ঠিক আছে।

Q3: WeakMap কেন দরকার?

উত্তর: মেমোরি লিক আটকানোর জন্য। এটি অবজেক্টের রেফারেন্স অটোমেটিক ডিলিট করে দেয় যখন সেটি আর ব্যবহৃত হয় না।

Q4: WeakMap এর Key কেন Primitive (String/Number) হতে পারে না?

উত্তর: কারণ প্রিমিটিভ ভ্যালু গার্বেজ কালেক্টেড হয় না। WeakMap এর মূল উদ্দেশ্যই হলো গার্বেজ কালেকশনে সাহায্য করা, তাই শুধু অবজেক্ট সাপোর্ট করে।

🧠 অধ্যায় ১৮ সারাংশ (Summary)

  • Set: ইউনিক ভ্যালু এবং সুপার ফাস্ট লুকআপ
  • Map: অবজেক্টের চেয়ে শক্তিশালী, যেকোনো টাইপের কী সাপোর্ট করে
  • WeakMap/WeakSet: মেমোরি ম্যানেজমেন্টের বস। গার্বেজ কালেকশন ফ্রেন্ডলি

Next Step: ডাটা স্ট্রাকচার শেষ। এখন আমরা স্ট্রিং নিয়ে জাদুকরী কাজ কারবার শিখব। পরের অধ্যায়: "Regular Expressions (RegEx) - From Fear to Mastery"।

🔒 কপিরাইট সুরক্ষিত কন্টেন্ট 🔒

কপি, স্ক্রিনশট, প্রিন্ট করা সম্পূর্ণ নিষিদ্ধ।