اگر میخواهید عملیات رایج نقشهها (Maps) را روی کد واقعی تمرین کنید، مستقیماً به بخش پایانی این صفحه بروید: تمرین عملیات Map
دومین ساختار اصلی ارائهشده توسط Collections Framework پیادهسازی یک دادهساختار کلاسیک است: ساختار Hashmap. این مفهوم جدید نیست و در ساختاردهی دادهها — چه در حافظه و چه خارج از آن — بنیادین است.
یک hashmap ساختاری است که قادر به ذخیرهی جفتهای کلید-مقدار (Key-Value Pairs) است. مقدار هر شیءای است که برنامهی شما نیاز به مدیریتش دارد و کلید چیزی است که میتواند آن شیء را نمایندگی کند.
فرض کنید نیاز به برنامهای دارید که با فاکتورها (Invoices) کار میکند، که هرکدام نمونهای از کلاس Invoice هستند. مقدارهای شما این نمونههای Invoice هستند و کلیدهای شما میتوانند شمارهی فاکتورها باشند. هر فاکتور شمارهای منحصربهفرد دارد.
بهطور کلی، هر مقدار به یک کلید متصل است، همانطور که یک فاکتور به شمارهی فاکتورش متصل است. با داشتن یک کلید مشخص میتوانید مقدار مربوطه را بازیابی کنید. معمولاً کلید یک شیء ساده است (مثلاً یک رشته یا عدد) اما مقدار میتواند هر پیچیدگیای داشته باشد.
پیش از آنکه جزئیات رابطهی Map را ببینید، این نکات را در ذهن داشته باشید:
Collections Framework رابطهی Map را برای پیادهسازی این مفهوم ارائه میدهد، همراه با دو extension: SortedMap و NavigableMap.
[دیاگرام: سلسلهمراتب رابطهی Map]
این سلسلهمراتب بسیار ساده است و مشابه سلسلهمراتب Set با SortedSet و NavigableSet است. SortedMap هم نوع معنایی مشابه SortedSet دارد: نقشهای که جفتهای کلید-مقدارش را بر اساس کلیدها مرتب نگه میدارد. NavigableMap هم همینطور است.
JDK چندین پیادهسازی از رابطهی Map ارائه میدهد که رایجترین آنها کلاس HashMap است.
دو پیادهسازی دیگر:
LinkedHashMap یک HashMap با ساختار داخلی برای حفظ ترتیب جفتهای کلید-مقدار است. پیمایش کلیدها یا جفتهای کلید-مقدار بر اساس ترتیب اضافهشدنشان خواهد بود.IdentityHashMap یک Map تخصصی است که فقط باید در موارد بسیار خاصی استفاده شود. این پیادهسازی بهجای equals() و hashCode() از اپراتور تطابق (==) برای مقایسهی مراجع کلیدها استفاده میکند. با احتیاط از آن استفاده کنید.شاید شنیده باشید Multimap چیست. Multimap مفهومی است که در آن یک کلید میتواند به بیش از یک مقدار متصل باشد. این مفهوم بهصورت مستقیم در Collections Framework پشتیبانی نمیشود. اما بعداً خواهید دید چگونه میتوانید نقشههایی با مقادیری که در واقع لیستی از مقادیر هستند ایجاد کنید. این الگو ساختارهای مشابه multimap ایجاد میکند.
همانطور که دیدید، Java SE 9 متدهایی به رابطههای List و Set برای ایجاد لیستها و مجموعههای غیرقابل تغییر اضافه کرد.
متدهای مشابهی هم روی رابطهی Map وجود دارد که نقشهها و entryهای غیرقابل تغییر ایجاد میکنند.
میتوانید بهسادگی با الگوی زیر یک Map ایجاد کنید:
خروجی این کد:
Map: {3=three, 1=one, 2=two}
یک نکته: فقط زمانی میتوانید از این الگو استفاده کنید که حداکثر ۱۰ جفت کلید-مقدار داشته باشید.
اگر تعداد بیشتری دارید، از الگوی دیگری استفاده کنید:
خروجی این کد:
Map: {1=one, 2=two, 3=three}
همچنین میتوانید این الگو را به شکل زیر بنویسید و از static imports برای بهبود خوانایی استفاده کنید:
خروجی این کد:
Map: {1=one, 2=two, 3=three}
محدودیتهایی روی این نقشهها و entryهای ایجادشده توسط متدهای کارخانهای وجود دارد، مشابه مجموعهها:
IllegalArgumentException دریافت خواهید کردرابطهی بین یک کلید و مقدار متصل به آن دو قانون ساده دارد:
این موضوع چندین نتیجه برای محتوای نقشه دارد:
Set داردSet داردCollection معمولی داردعملیاتهایی که میتوان روی یک نقشه تعریف کرد:
عملیاتهای کلاسیک مشابه مجموعهها هم وجود دارد:
همهی این عملیات و مفاهیم در رابطهی Map پیادهسازی شدهاند.
رابطهی Map نوع پایهای است که مفهوم نقشه را در JDK مدلسازی میکند.
هنگام انتخاب نوع کلیدها برای نقشههایتان بسیار محتاط باشید. استفاده از کلیدهای mutable نه ممنوع است اما خطرناک و توصیهنشده است. وقتی کلیدی به نقشه اضافه شد، تغییر آن ممکن است مقدار hash code و هویتش را تغییر دهد. این میتواند باعث غیرقابل بازیابی شدن جفت کلید-مقدار شود یا هنگام query کردن نقشه مقدار متفاوتی دریافت کنید.
رابطهی Map یک رابطهی عضو به نام Map.Entry برای مدلسازی یک جفت کلید-مقدار تعریف میکند. این رابطه سه متد برای دسترسی به کلید و مقادیر دارد:
getKey(): خواندن کلیدgetValue() و setValue(value): خواندن و بهروزرسانی مقدار متصل به کلیداشیاء Map.Entry که از یک نقشه دریافت میکنید، ویوهایی روی محتوای نقشه هستند. تغییر مقدار یک entry در نقشه منعکس میشود و بالعکس. به همین دلیل نمیتوانید کلید را در این شیء تغییر دهید: ممکن است نقشه خراب شود.
میتوانید با الگوی زیر نقشهها ایجاد کنید و جفتهای کلید-مقدار اضافه کنید. در مثالهای بعدی الگوهای بیشتری خواهید دید.
خروجی مثال بالا:
Size of the map: 4
Ages: {Bob=30, Alice=25, David=35, Carol=28}
میتوانید مقدار را از کلیدش دریافت کنید:
خروجی کد بالا:
Ages: {Bob=30, David=35, Carol=28, Alice=25}
Alice's age: 25
Eve's age: null
Eve's age (with default): 0
همچنین میتوانید وجود یک کلید یا مقدار مشخص را بررسی کنید:
خروجی کد بالا:
Ages: {Carol=28, David=35, Bob=30, Alice=25}
Contains Bob as a key? true
Contains Bob as a value? false
Contains age 28 as a value? true
Contains age 28 as a key? false
میتوانید مقدار متصل به یک کلید موجود را بهروز کنید یا فقط در صورتی که کلید در نقشه وجود نداشته باشد، آن را اضافه کنید.
خروجی کد بالا:
Ages: {David=35, Carol=28, Bob=30, Alice=25}
Previous Alice age: 25
Previous Alice age: 26
Current ALice age: 26
Previous Eve age: null
Updated map: {David=35, Carol=28, Bob=30, Eve=22, Alice=26}
After removing David: {Carol=28, Bob=30, Eve=22, Alice=26}
سه کلکشن میتوانید از یک نقشه دریافت کنید:
خروجی کد بالا:
Key set: [Bob, David, Carol, Alice]
Value collection: [30, 35, 28, 25]
Entry set: [Bob=30, David=35, Carol=28, Alice=25]
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://dev.java/learn/