Java HashMap & HashSet: A/L එකෙන් එහාට! Data Structures Sinhala Guide

ආයුබෝවන්, කොහොමද ඉතින්? Java වල Data Structures ගැන කතා කරද්දී, HashMap එකයි HashSet එකයි කියන්නේ අපිට නිතරම වගේ පාවිච්චි කරන්න වෙන, හරිම වැදගත් concepts දෙකක්. ඔයා Java developer කෙනෙක් නම්, මේ දෙක හරියටම තේරුම් අරන් ඉන්න එක හරිම වටිනවා. මොකද මේවා තමයි අපේ applications වේගවත් කරන්න, efficient කරන්න උදව් කරන්නේ. අද මේ article එකෙන් අපි මේ HashMap සහ HashSet කියන data structures දෙක ගැන සරලව, පැහැදිලිව, ප්රායෝගික උදාහරණ එක්ක කතා කරමු. අපි එහෙනම් වැඩේට බහිමු!
HashMap කියන්නේ මොකක්ද?
හරි, මුලින්ම අපි බලමු මොකක්ද මේ HashMap කියන්නේ කියලා. සරලවම කිව්වොත්, HashMap එකක් කියන්නේ key-value pairs විදිහට දත්ත ගබඩා කරන්න පාවිච්චි කරන collection එකක්. හිතන්නකෝ ඔයා ළඟ telephone directory එකක් තියෙනවා කියලා. ඒකේ හැම නමකටම (Key) අදාළ phone number එකක් (Value) තියෙනවා නේද? හරියටම ඒ වගේ තමයි HashMap එකත් වැඩ කරන්නේ. හැම Key එකක්ම Unique වෙන්න ඕනේ. ඒ කියන්නේ එකම Key එක දෙපාරක් පාවිච්චි කරන්න බෑ. හැබැයි Value එකක් ඕනෙතරම් පාරක් පාවිච්චි කරන්න පුළුවන්. ඒ වගේම, මේක Hashtable එකේ non-synchronized version එකක්. ඒ කියන්නේ multi-threading environments වලදී මේක භාවිතා කරනවා නම් extra precautions ගන්න වෙනවා.
HashMap එකේ තියෙන ලොකුම වාසිය තමයි දත්ත හොයාගන්න, add කරන්න, delete කරන්න තියෙන වේගය. සාමාන්යයෙන් මේ operations වලට O(1) average time complexity එකක් තියෙනවා. ඒ කියන්නේ data quantity එක කොච්චර වැඩි වුණත්, වැඩේ වෙන්නේ එකම වේගයකින් වගේ තමයි. මේක වෙන්නේ hashing කියන technique එක පාවිච්චි කරන නිසා. ඒ කියන්නේ හැම Key එකකටම අදාළව Unique hash code එකක් generate කරලා, ඒක පාවිච්චි කරලා data එක memory එකේ ගබඩා කරනවා. ඒ නිසාම HashMap එකක data ගබඩා වෙලා තියෙන Order එකක් නෑ. ඕන එකක් ඕන තැනක ගබඩා වෙන්න පුළුවන්. අපිට අවශ්ය Key එක දාලා අදාළ Value එක ගන්න පුළුවන්. ඒ වගේම HashMap වලට null
Keys සහ null
Values තියාගන්නත් පුළුවන්. හැබැයි තියෙන්න පුළුවන් එකම null
Key එකයි.
දැන් අපි පොඩි Code Example එකකින් බලමු කොහොමද HashMap එකක් පාවිච්චි කරන්නේ කියලා.
import java.util.HashMap;
import java.util.Map; // Map interface එකත් import කරගන්න එක හොඳ පුරුද්දක්
public class HashMapExample {
public static void main(String[] args) {
// HashMap එකක් හදාගමු
// Key එක String, Value එක Integer
Map<String, Integer> studentMarks = new HashMap<>();
// Data add කරමු: put() method එක පාවිච්චි කරලා
studentMarks.put("නිමල්", 85);
studentMarks.put("කමල්", 78);
studentMarks.put("සුනිල්", 92);
studentMarks.put("අමරා", 65);
studentMarks.put("නිමල්", 90); // 'නිමල්' කියන Key එකට අලුත් Value එක replace වෙනවා
System.out.println("මුලින්ම තියෙන Marks: " + studentMarks);
// Value එකක් ගන්න: get() method එක පාවිච්චි කරලා
int nimalMark = studentMarks.get("නිමල්");
System.out.println("නිමල්ගේ Marks: " + nimalMark); // Output: නිමල්ගේ Marks: 90
// Key එකක් තියෙනවද බලන්න: containsKey() method එකෙන්
boolean hasKamal = studentMarks.containsKey("කමල්");
System.out.println("කමල් කියන Key එක තියෙනවද?: " + hasKamal); // Output: කමල් කියන Key එක තියෙනවද?: true
// Value එකක් තියෙනවද බලන්න: containsValue() method එකෙන්
boolean hasMark92 = studentMarks.containsValue(92);
System.out.println("92 කියන Value එක තියෙනවද?: " + hasMark92); // Output: 92 කියන Value එක තියෙනවද?: true
// Data remove කරමු: remove() method එකෙන්
studentMarks.remove("අමරා");
System.out.println("අමරා remove කලාට පස්සේ: " + studentMarks);
// හැම Key එකක්ම ගන්න: keySet() method එකෙන්
System.out.println("සියලුම Keys: " + studentMarks.keySet());
// හැම Value එකක්ම ගන්න: values() method එකෙන්
System.out.println("සියලුම Values: " + studentMarks.values());
// HashMap එකේ ප්රමාණය: size() method එකෙන්
System.out.println("HashMap එකේ ප්රමාණය: " + studentMarks.size());
// හැම entry එකක්ම iterate කරන්න
System.out.println("\nHashMap එක iterate කරමු:");
for (Map.Entry<String, Integer> entry : studentMarks.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
// HashMap එක clear කරන්න
studentMarks.clear();
System.out.println("HashMap එක Clear කලාට පස්සේ: " + studentMarks);
}
}
මේ Code එකෙන් ඔයාට HashMap එකක මූලික operation ටික හොඳට තේරෙන්න ඇති කියලා හිතනවා. බලන්නකෝ, කොච්චර සරලද කියලා!
HashSet කියන්නේ මොකක්ද?
හරි, දැන් අපි යමු HashSet පැත්තට. HashMap එකේ key-value pairs ගබඩා කරනවා වගේ නෙවෙයි, HashSet එකක ගබඩා කරන්නේ unique elements sets එකක්. ඒ කියන්නේ HashSet එකකට එකම element එක දෙපාරක් add කරන්න බෑ. ඔයා එකම element එක දෙපාරක් add කරන්න හැදුවොත්, ඒක add වෙන්නේ නෑ. Error එකක් එන්නෙත් නෑ, හැබැයි add වෙන්නෙත් නෑ! හරියට ගණිතයේදී Set එකක් වගේ තමයි. ඒ වගේම මේකේ දත්ත තියෙන Order එකක් නෑ. Data add වෙන විදිහටම තියෙයි කියලා හිතන්න බෑ. ඕන තැනක ගබඩා වෙන්න පුළුවන්. ඒ වගේම HashSet එකක් ඇතුළේ වැඩ කරන්නෙත් HashMap එකක් පාවිච්චි කරලා තමයි. HashSet එකේ හැම element එකක්ම HashMap එකේ Key එකක් විදිහට ගබඩා වෙනවා, ඒත් Value එක විදිහට Java වල Dummy Object එකක් (PRESENT
කියන static final Object එකක්) පාවිච්චි කරනවා. නියමයි නේද මේ concept එක!
HashSet එකේ ප්රධාන වාසිය තමයි element එකක් set එකේ තියෙනවද නැද්ද කියලා බලන්න, add කරන්න, remove කරන්න තියෙන වේගය. මේ operations වලටත් සාමාන්යයෙන් O(1) average time complexity එකක් තියෙනවා. ඒ නිසා duplicates remove කරන්න, unique elements list එකක් හදාගන්න වගේ දේවල් වලට HashSet එක පට්ටම useful වෙනවා.
දැන් අපි මේකත් පොඩි Code Example එකකින් බලමු.
import java.util.HashSet;
import java.util.Set; // Set interface එකත් import කරගන්න එක හොඳයි
public class HashSetExample {
public static void main(String[] args) {
// HashSet එකක් හදාගමු
Set<String> fruits = new HashSet<>();
// Elements add කරමු: add() method එකෙන්
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Orange");
fruits.add("Apple"); // මේක add වෙන්නේ නෑ, මොකද 'Apple' already තියෙන නිසා
fruits.add("Mango");
System.out.println("මුලින්ම තියෙන Fruits: " + fruits); // Output එකේ 'Apple' තියෙන්නේ එකයි
// Element එකක් තියෙනවද බලන්න: contains() method එකෙන්
boolean hasBanana = fruits.contains("Banana");
System.out.println("Banana තියෙනවද?: " + hasBanana); // Output: Banana තියෙනවද?: true
// Element එකක් remove කරන්න: remove() method එකෙන්
fruits.remove("Orange");
System.out.println("Orange remove කලාට පස්සේ: " + fruits);
// HashSet එකේ ප්රමාණය: size() method එකෙන්
System.out.println("HashSet එකේ ප්රමාණය: " + fruits.size());
// හැම element එකක්ම iterate කරන්න
System.out.println("\nHashSet එක Iterate කරමු:");
for (String fruit : fruits) {
System.out.println(fruit);
}
// HashSet එක clear කරන්න
fruits.clear();
System.out.println("HashSet එක Clear කලාට පස්සේ: " + fruits);
}
}
බලන්න, කොච්චර සරලව unique elements manage කරන්න පුළුවන්ද කියලා!
HashMap සහ HashSet අතර වෙනස
දැන් අපි මේ HashMap සහ HashSet කියන දාම් දෙක අතර තියෙන ප්රධාන වෙනස්කම් මොනවද කියලා චුට්ටක් බලමු. මේ වෙනස්කම් හොඳට තේරුම් ගත්තොත්, ඔයාට ඕන වෙලාවට නිවැරදි එක තෝරගන්න ලේසි වෙයි.
ලක්ෂණය (Feature) | HashMap | HashSet |
---|---|---|
මූලික අරමුණ (Purpose) | Key-Value pairs ගබඩා කිරීමට. | Unique elements ගබඩා කිරීමට. |
ගබඩා කිරීම (Storage) | Key සහ Value දෙකම ගබඩා කරයි. | Elements පමණක් ගබඩා කරයි (Key එකක් ලෙස). |
Duplicates | Keys Unique විය යුතුයි. Values duplicate වෙන්න පුළුවන්. | Elements Unique විය යුතුයි (Duplicates වලට ඉඩක් නෑ). |
අභ්යන්තර ක්රියාකාරීත්වය (Internal Implementation) | Hashing Principle එක මත පදනම් වූ Hashtable එකක් භාවිතා කරයි. | HashMap එකක් අභ්යන්තරව භාවිතා කරයි (HashSet element එක HashMap එකේ Key එක ලෙසත්, Dummy Object එක Value ලෙසත්). |
Interfaces | Map interface එක implement කරයි. |
Set interface එක implement කරයි. |
Methods | put() , get() , containsKey() , keySet() , values() , entrySet() වැනි methods ඇත. |
add() , contains() , remove() වැනි methods ඇත. |
Order | ගබඩා වූ Order එකක් පවත්වාගෙන යන්නේ නෑ. (Unordered) | ගබඩා වූ Order එකක් පවත්වාගෙන යන්නේ නෑ. (Unordered) |
Null Values/Keys | එක් null Key එකක් සහ ඕනෑම ගණනක null Values වලට ඉඩ දෙයි. |
එක් null element එකකට ඉඩ දෙයි. |
ඔන්න ඕකයි කතාව! මේ table එකෙන් ඔයාට මේ දෙක අතර තියෙන ලොකුම වෙනස්කම් පැහැදිලි වෙන්න ඇති.
ප්රායෝගික භාවිතය සහ හොඳම පුරුදු (Practical Usage and Best Practices)
දැන් අපි බලමු ප්රායෝගිකව මේ HashMap සහ HashSet කොයි වගේ අවස්ථාවලදීද අපිට වැඩේට බස්සන්න පුළුවන් කියලා, ඒ වගේම හොඳම පුරුදු මොනවද කියලා.
HashMap භාවිතය:
- Caching: ඉක්මනින් දත්ත access කරන්න ඕන අවස්ථාවලදී. උදාහරණයක් විදිහට, database එකකින් load කරන user data cache කරන්න පුළුවන් user ID එක Key එක විදිහට අරන්.
- Frequency Counting: යම් දෙයක සිදුවීම් ගණන ගණන් කරන්න. උදාහරණයක් විදිහට, String එකක හැම අකුරක්ම කී වතාවක් තියෙනවද කියලා බලන්න.
- Mapping IDs to Objects: ID එකක් දීලා අදාළ Object එක ගන්න. උදාහරණයක් විදිහට, Product ID එකට අදාළ Product Object එක ගන්න.
- Configuration Settings: Configuration settings key-value pairs විදිහට ගබඩා කරන්න.
HashSet භාවිතය:
- Removing Duplicates: List එකක තියෙන duplicate elements අයින් කරලා unique elements ටික විතරක් ගන්න. මේක ගොඩක්ම useful.
- Checking for Uniqueness: යම් element එකක් collection එකක තියෙනවද කියලා ඉක්මනින් බලන්න. උදාහරණයක් විදිහට, website එකක user names unique ද කියලා බලන්න.
- Membership Testing: යම් element එකක් set එකක සාමාජිකයෙක්ද කියලා බලන්න.
වැදගත් පොයින්ට් එකක්: hashCode()
සහ equals()
ඔයා custom objects (ඔයාම හදන Class objects) HashMap එකක Key එකක් විදිහට හරි, HashSet එකක element එකක් විදිහට හරි පාවිච්චි කරනවා නම්, අනිවාර්යයෙන්ම ඒ object එකේ hashCode()
සහ equals()
methods දෙක override කරන්න ඕනේ. මොකද, HashMap එකයි HashSet එකයි වැඩ කරන්නේ මේ methods දෙක පාවිච්චි කරලා තමයි. equals()
method එකෙන් කියන්නේ objects දෙකක් සමානද කියලා, hashCode()
method එකෙන් කියන්නේ ඒ objects වල hash value එක. මේ දෙක හරියට override කරලා නැත්නම්, ඔයා හිතන විදිහට වැඩේ වෙන්නේ නෑ. උදාහරණයක් විදිහට, එකම object එක දෙපාරක් add වුණත් HashSet එකේ duplicate වෙන්න පුළුවන්, නැත්නම් ඔයාට අවශ්ය key එකට අදාළ value එක HashMap එකෙන් හොයාගන්න බැරි වෙන්න පුළුවන්. IntelliJ IDEA වගේ IDE වල auto-generate කරන්න මේ options තියෙනවා. ඒ නිසා බය වෙන්න එපා!
LinkedHashMap
සහ LinkedHashSet
ඔයාට data එක add කරපු order එක හෝ access කරපු order එක පවත්වාගෙන යන්න ඕනේ නම්, LinkedHashMap
සහ LinkedHashSet
කියන ඒවා පාවිච්චි කරන්න පුළුවන්. මේවා HashMap/HashSet වගේම තමයි, හැබැයි add කරපු order එක මතක තියාගන්නවා. මේවා ගැන වෙනම article එකකින් කතා කරමු.
නිගමනය (Conclusion)
හරි, අද අපි Java වල තියෙන පට්ටම වැදගත් Data Structures දෙකක් වෙන HashMap සහ HashSet ගැන හොඳට කතා කලා. මේ දෙකම Java Collections Framework එකේ වැදගත් කොටස් දෙකක්, ඒ වගේම අපේ Applications වල Performance එක වැඩි කරන්න මේවා අනිවාර්යයෙන්ම උපකාරී වෙනවා. HashMap එක Keys සහ Values ගබඩා කරන්නත්, HashSet එක Unique Elements ගබඩා කරන්නත් භාවිතා කරනවා කියලා අපි දැක්කා. ඒ වගේම මේවා කොහොමද ප්රායෝගිකව භාවිතා කරන්නේ, සහ හොඳම පුරුදු මොනවද කියලත් අපි සාකච්ඡා කලා. විශේෂයෙන්ම custom objects පාවිච්චි කරද්දී hashCode()
සහ equals()
methods වල වැදගත්කම ගැනත් මතක තියාගන්න.
දැන් ඔයාට මේ concepts දෙක ගැන හොඳ අවබෝධයක් තියෙනවා ඇති කියලා හිතනවා. වැදගත්ම දේ තමයි මේවා ඔයාගේම code එකේ apply කරලා බලන එක. එතකොට තමයි මේවා හරියටම ඔලුවට යන්නේ. මොකද ප්රායෝගිකව කරනකොට තමයි ගොඩක් දේවල් ඉගෙන ගන්න පුළුවන් වෙන්නේ.
ඔයාට මේ ගැන තවත් ප්රශ්න තියෙනවද? නැත්නම් මේකේ තේරෙන්නේ නැති තැන් තියෙනවනම් පහළින් comment එකක් දාන්න. අපි හැමෝම එකතු වෙලා මේවා ගැන කතා කරමු, තවත් අලුත් දේවල් ඉගෙන ගමු. ලංකාවේ programmersලා හැටියට අපි හැමෝම එකතු වෙලා knowledge share කරගමු!