یک Map ساختار دادهای برای ذخیرهی جفتهای کلید-مقدار است. این ساختار مشابه دیکشنریها در سایر زبانهای برنامهنویسی است. رابط Map عملیاتهایی را تعریف میکند که میتوانید روی یک Map انجام دهید.
Java چندین پیادهسازی مختلف Map دارد. 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 ورودیهایی به Map اضافه کنید.
fruitPrices.put("apple", 100);
fruitPrices.put("pear", 80);
// => { "apple" => 100, "pear" => 80 }
هر کلید فقط میتواند با یک مقدار مرتبط باشد.
فراخوانی put با همان کلید، مقدار آن کلید را بهروزرسانی میکند.
fruitPrices.put("pear", 40);
// => { "apple" => 100, "pear" => 40 }
برای گرفتن مقدار یک کلید از get استفاده کنید.
fruitPrices.get("apple"); // => 100
برای دیدن اینکه آیا Map یک کلید خاص را دارد یا نه، از 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
میتوانید از متدهای keySet یا values استفاده کنید تا کلیدها یا مقادیر یک Map را بهترتیب بهصورت یک Set یا یک مجموعه به دست آورید.
fruitPrices.keySet(); // Returns "apple" and "pear" in a set
fruitPrices.values(); // Returns 100 and 80, in a Collection
hashCode و equals استفاده میکندHashMapها از متد hashCode و equals شیء استفاده میکنند تا بفهمند مقدارهای یک کلید را کجا ذخیره کنند و چگونه بازیابیشان کنند. به همین دلیل، مهم است که مقادیر برگشتی آنها بین ذخیرهکردن و بازیابی تغییر نکنند، وگرنه ممکن است HashMap نتواند مقدار را پیدا کند.
برای مثال، فرض کنید کلاس زیر را داریم که بهعنوان کلید یک Map استفاده میشود:
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 استفاده از 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 را از پیش پر میکنند و پس از ساختهشدن فقطخواندنی میشوند.
Map.copyOf یک نسخهی فقطخواندنی از یک Map میسازد.
Map<String, Integer> readOnlyFruitPrices = Map.copyOf(fruitPrices);
فراخوانی متدهایی مانند put، remove یا clear منجر به یک UnsupportedOperationException میشود.