HashMap

قبلاً با مفهوم Map به عنوان وسیله ای برای نگه داری زوج های کلید-مقدار آشنا شدیم، کلاس HashMap زیر کلاس AbstractMap است و از الگوریتم درهم سازی برای نگه داری زوج ها نگه داری می کند. مهم ترین مزیت HashMap این است که دسترسی به کلید ها در زمان بسیار کوتاهی صورت می گیرد و با داشتن کلید به سرعت می توانیم مقدار را به دست بیاوریم. از HashMap می توان برای ساخت جداولی همچون دفترچه تلفن ، لیست نمرات و غیره استفاده کرد.به علاوه در بسیاری از کاربرد های هوش مصنوعی از HashMap برای شناسایی گره های تکراری در جست و جوهای پیشرفته استفاده می شود. در HashMap مقدار null هم به عنوان کلید و هم به عنوان مقدار مجاز است ولی حداکثر یک کلید با مقدار null می تواند در آن وجود داشته باشد. کلاس HashMap از طریق مسیر java.util.HashMap قابل دستیابی است. برای ساخت شی جدید از کلاس HashMap باید از یکی از سازنده های زیر استفاده کنیم :

HashMap()

یک HashMap جدید با جدول نگه دارنده خالی ایجاد می کند.

HashMap(int capacity)

یک HashMap جدید با جدول نگه دارنده ای با اندازه capacity ایجاد می کند ، البته هر زمان که لازم باشد جدول نگه دارنده به صورت خودکار افزایش اندازه خواهد داشت.

HashMap(int capacity,float loadFactor)

مشابه سازنده قبلی است با این تفاوت که پارامتر loadFactor تعیین می کند که چه زمان اندازه جدول نگه دارنده باید افزایش یابد.

HashMap(Map mp)

یک HashMap جدید ایجاد می کند و اعضای mp را به آن اضافه می کند. متد های مهم HashMap در جدول زیر آمده اند :

متد توضیح
clear() کل مجموعه را پاک می کند.
containsKey(Object key) بررسی می کند که شی مورد نظر در بخش کلید ها قرار دارد یا خیر؟
containsValue(Object value) بررسی می کند که شی مورد نظر رد بخش مقادیر قرار دارد یا خیر؟
entrySet() یک مجموعه از کل مقادیر موجود در HashMap بر می گرداند.
get(Object key) مقدار متناظر با یک کلید را بر می گرداند.
isEmpty() بررسی می کند که مجموعه خالی است یا خیر؟
keySet() مجموعه کلید ها را بر می گرداند.
put(Object k,Object v) مقدار v را به کلید k نسبت می دهد.
putAll(Map mp) تمام اعضای mp را به مجموعه اضافه می کند.
remove(Object key) کلید مورد نظر و مقدار متناظر با آن را از مجموعه حذف می کند.
size() اندازه مجموعه (تعداد کلید ها) را بر می گرداند.
Collection values() مجموعه مقادیر را به صورت یک کالکشن بر می گرداند.

در مثال زیر یک دفترچه تلفن ساده طراحی می کنیم که کلید نام افراد و مقدار شماره آن هاست ، هدف آن است که با داشتن نام اشخاص به سرعت بتوانیم شماره آن ها را بازیابی کنیم.

import java.util.HashMap;

public class HashMapDemo
{
    public static void main(String[] args) 
    {
        HashMap myHashMap = new HashMap();

        myHashMap.put("Jenny", 0916532365);
        myHashMap.put("Peter", 0912534689);
        myHashMap.put("Mary Jane", 09152136458);
        myHashMap.put("Azhar", 09132536489);

        System.out.println(myHashMap.get("Jenny"));
    }
}
0916532365

در کد بالا ابتدا یک سری داده با استفاده از متد ()put به HashMap اضافه می کنیم ، کلید نام افراد و مقدار شماره آن هاست. در ادامه با استفاده از متد ()get شماره شخصی با نام Jenny را از مجموعه استخراج کرده و چاپ می کنیم. می دانیم که در ساختار HashMap کلید منحصر به فرد است و کلید تکراری وجود ندارد ولی در یک دفترچه تلفن است ممکن است برای یک نفر چندین شماره ثبت کرده باشیم، برای اینکه بتوانیم به یک کلید چندین مقدار نسبت دهیم باید از راهکاری ابتکاری استفاده کنیم. برای این منظور می توانیم مقدار را به صورت یک کالکشن در نظر بگیریم. در ادامه با این روش آشنا می شویم.

   1: import java.util.HashMap;
   2: import java.util.TreeSet;
   3: 
   4: public class HashMapDemo
   5: {
   6:     static HashMap myHashMap = new HashMap();
   7: 
   8:     static void putNumber(String name, String phoneNumber) 
   9:     {
  10:         TreeSet list;
  11: 
  12:         if (myHashMap.get(name) == null) 
  13:         {
  14:             list = new TreeSet();
  15:         }
  16:         else 
  17:         {
  18:             list = (TreeSet)myHashMap.get(name);
  19:         }
  20: 
  21:         list.add(phoneNumber);
  22: 
  23:         myHashMap.put(name, list);
  24:     }
  25: 
  26:     public static void main(String[] args) 
  27:     {
  28:         putNumber("Jenny", "0916532365");
  29:         putNumber("Peter", "0912534689");
  30:         putNumber("Jenny", "09152136458");
  31:         putNumber("Azhar", "09132536489");
  32: 
  33:         System.out.println(myHashMap.get("Jenny"));
  34:     }
  35: }
[09152136458, 0916532365]

در کد بالا از HashMap به شیوه ای استفاده کردیم که کلید در آن از نوع String و مقدار در آن TreeSet است لذا مقدار در آن می تواند شامل چندین عضو باشد مهم ترین قسمت کد بالا متد phoneNumber است. در ابتدای این متد با استفاده از یک if مشخص می کنیم که آیا قبلاً مقداری برای کلید name نسبت داده شد است؟ اگر خروجی متد ()get برابر با null باشد یعنی قبلاً به این کلید (name) هیچ مقداری نسبت داده نشده است لذا یک لیست خالی از جنس TreeSet ایجاد می کنیم ، در غیر این صورت (کد داخل بخش else) ، لیست نمراتی که قبلاً به کلید (name) نسبت داده شده بود را استخراج می کنیم. بعد از بررسی بالا می توانیم شماره جدید را با استفاده از متد ()add به لیست اضافه کنیم (می دانیم که TreeSet مقدار تکراری نگه داری نمی کند و به علاوه اعضا در آن به صورت مرتب نگه داری می شوند) ، پس از آن با استفاده از متد ()put لیست جدید را به کلید (name) نسبت می دهیم. همانطور که در خروجی می کنید هنگامی که عبارت “Jenny” را به عنوان کلید myHashMap به کار می بریم خروجی به صورت یک لیست دو عنصری چاپ می شود (در حقیقت محتوای یک TreeSet چاپ می شود). در این مثال با بعضی از متد های مهم HashMap آشنا می شویم.

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class HashMapDemo
{
    public static void main(String[] args) 
    {
        HashMap myHashMap = new HashMap();

        myHashMap.put("A", 10);
        myHashMap.put("B", 20);
        myHashMap.put("C", 30);
        myHashMap.put("D", 40);
        myHashMap.put("E", 50);

        //containsKey
        System.out.println(myHashMap.containsKey("A"));
        System.out.println(myHashMap.containsKey(10));

        //containsValue
        System.out.println(myHashMap.containsValue("A"));
        System.out.println(myHashMap.containsValue(10));

        Set allValue = myHashMap.entrySet();

        for (Map.Entry x : allValue) 
        {
            System.out.println(x.getKey() + " : " + x.getValue());
        }
    }
}
true
false
false
true
D : 40
E : 50
A : 10
B : 20
C : 30

در کد بالا ابتدا یک HashMap جدید ایجاد کردیم و با استفاده از متد ()put زوج های کلید و مقداری را در آن درج کردیم. سپس متد ()containsKey را مورد بررسی قرار دادیم ، این متد وجود یا عدم وجود کلید ها را بررسی می کند ، می بینیم که کلید A وجود دارد ولی کلید 10 وجود ندارد . سپس از آن متد ()containsValue را مورد بررسی قرار دادیم، این متد وجود یا عدم وجود مقدار (و نه کلید) را بررسی می کند ، می بینیم که مقدار A وجود ندارد (A در بخش کلید ها وجود داشت) ولی مقدار 10 وجود دارد (10 در بخش کلید ها وجود نداشت). پس از آن با استفاده از متد ()entrySet تمام زوج های کلید-مقدار مجموعه را در یک Set با اعضایی از نوع Map.Entry ریختیم. در داخل یک حلقه for هر آیتم از allValue را در متغیر x استخراج کرده سپس با متد ()getKey کلید و با متد ()getValue مقدار متناظر با آن را به دست آورده و چاپ کردیم.