ম্যাপ হলো কী (key) ও মানের জোড়া সংরক্ষণ করার একটি ডেটা স্ট্রাকচার। এটি অন্য প্রোগ্রামিং ভাষার ডিকশনারির মতো। ম্যাপ ইন্টারফেসে সংজ্ঞায়িত থাকে কোন কোন অপারেশন আপনি একটি ম্যাপ নিয়ে করতে পারেন।
Java-তে বিভিন্ন রকমের ম্যাপ ইমপ্লিমেন্টেশন আছে। এগুলোর মধ্যে HashMap বেশ কমন।
// Make an instance
Map<String, Integer> fruitPrices = new HashMap<>();
একটি Map ভ্যারিয়েবল ডিফাইন করার সময় উপরের উদাহরণের মতো নির্দিষ্ট টাইপ নয়, বরং Map টাইপ হিসেবেই ভ্যারিয়েবলটি ডিফাইন করার পরামর্শ দেওয়া হয়।
এই অভ্যাসের ফলে পরে Map ইমপ্লিমেন্টেশন বদলানো সহজ হয়।
HashMap-এ একটি কপি কনস্ট্রাক্টরও আছে।
// Make a copy of a map
Map<String, Integer> copy = new HashMap<>(fruitPrices);
put দিয়ে ম্যাপে এন্ট্রি যোগ করুন।
fruitPrices.put("apple", 100);
fruitPrices.put("pear", 80);
// => { "apple" => 100, "pear" => 80 }
প্রতিটি কী (key)-এর সাথে কেবল একটি মান যুক্ত থাকতে পারে।
একই কী (key) দিয়ে put কল করলে সেই কী (key)-এর মান আপডেট হয়ে যাবে।
fruitPrices.put("pear", 40);
// => { "apple" => 100, "pear" => 40 }
একটি কী (key)-এর মান পেতে get ব্যবহার করুন।
fruitPrices.get("apple"); // => 100
ম্যাপে কোনো নির্দিষ্ট কী (key) আছে কি না দেখতে containsKey ব্যবহার করুন।
fruitPrices.containsKey("apple"); // => true
fruitPrices.containsKey("orange"); // => false
remove দিয়ে এন্ট্রি সরিয়ে ফেলুন।
fruitPrices.put("plum", 90); // Add plum to map
fruitPrices.remove("plum"); // Removes plum from map
size মেথডটি এন্ট্রির সংখ্যা রিটার্ন করে।
fruitPrices.size(); // Returns 2
ম্যাপের কী (key) গুলোকে একটি সেট হিসেবে আর মানগুলোকে একটি কালেকশন হিসেবে পেতে আপনি keySet বা values মেথড ব্যবহার করতে পারেন।
fruitPrices.keySet(); // Returns "apple" and "pear" in a set
fruitPrices.values(); // Returns 100 and 80, in a Collection
hashCode ও equals ব্যবহার করেHashMap কোনো মান কোথায় সংরক্ষণ করবে আর একটি কী (key)-এর মান কীভাবে খুঁজে বের করবে, তা ঠিক করার জন্য অবজেক্টের hashCode ও equals মেথড ব্যবহার করে। এই কারণে এটা জরুরি যে মান সংরক্ষণ করা আর সেটি ফেরত পাওয়ার মাঝে এদের রিটার্ন ভ্যালু বদলাবে না, নইলে HashMap হয়তো মানটি খুঁজে পাবে না।
উদাহরণস্বরূপ, ধরা যাক আমাদের নিচের ক্লাসটি আছে, যেটি একটি ম্যাপের কী (key) হিসেবে ব্যবহার করা হবে:
public class Stock {
private String name;
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
return Objects.hash(name);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (Objects.equals(Stock.class, obj.getClass()) && obj instanceof Stock other) {
return Objects.equals(name, other.name);
}
return false;
}
}
hashCode আর equals নির্ভর করে name ফিল্ডের উপর, যেটি setName দিয়ে বদলানো যায়।
hashCode বদলে দিলে অবাক করার মতো ফল পাওয়া যেতে পারে:
Stock stock = new Stock();
stock.setName("Beanies");
Map<Stock, Integer> stockCount = new HashMap<>();
stockCount.put(stock, 80);
stockCount.get(stock); // Returns 80
Stock other = new Stock();
other.setName("Beanies");
stockCount.get(other); // Returns 80 because "other" and "stock" are equal
stock.setName("Choccies");
stockCount.get(stock); // Returns null because hashCode value has changed
stockCount.get(other); // Also returns null because "other" and "stock" are not equal
stock.setName("Beanies");
stockCount.get(stock); // HashCode restored, so returns 80 again
stockCount.get(other); // Also returns 80 again because "other" and "stock" are back to equal
ম্যাপ তৈরির আরেকটি কমন উপায় হলো Map.of বা Map.ofEntries ব্যবহার করা।
// Using Map.of
Map<String, Integer> temperatures = Map.of("Mon", 30, "Tue", 28, "Wed", 32);
// or using Map.ofEntries
Map<String, Integer> temperatures2 = Map.ofEntries(
Map.entry("Mon", 30),
Map.entry("Tue", 28),
Map.entry("Wed", 32)
);
HashMap-এর বিপরীতে এগুলো শুরুতেই ম্যাপটি ভরে দেয় আর তৈরি হওয়ার পরপরই রিড-অনলি হয়ে যায়।
Map.copyOf একটি ম্যাপের রিড-অনলি কপি তৈরি করে।
Map<String, Integer> readOnlyFruitPrices = Map.copyOf(fruitPrices);
put, remove বা clear-এর মতো মেথড কল করলে একটি UnsupportedOperationException থ্রো হয়।