اگر میخواهید عملیات رایج لیستها را روی کد واقعی تمرین کنید، میتوانید مستقیماً به بخش پایانی این صفحه بروید: تمرین عملیات لیست
List دو قابلیت جدید نسبت به کلکشنهای ساده اضافه میکند:
در حالی که رابطهی Collection پیادهسازی خاصی در Collections Framework ندارد و به پیادهسازیهای زیرمجموعههایش وابسته است، رابطهی List دو پیادهسازی دارد: ArrayList و LinkedList. همانطور که از نامشان پیداست، اولی بر پایهی یک آرایهی داخلی و دومی بر پایهی یک لیست پیوندی دوطرفه (Doubly-Linked List) ساخته شده است.
آیا یکی از این دو پیادهسازی از دیگری بهتر است؟ اگر مطمئن نیستید کدام را انتخاب کنید، احتمالاً بهترین گزینهی شما ArrayList است.
آنچه در دههی ۱۹۶۰ دربارهی برتری لیستهای پیوندی در عملیات درج و حذف صادق بود، دیگر امروزه صادق نیست. سختافزارهای مدرن، کشهای CPU و اثر Pointer Chasing، برتری لیستهای پیوندی در درج و حذف را به شدت کاهش دادهاند. پیمایش عناصر یک ArrayList بسیار سریعتر از یک LinkedList است. دلیل اصلی این تفاوت هم دقیقاً Pointer Chasing و Cache Missهای CPU است.
با این حال، همچنان مواردی وجود دارد که لیست پیوندی سریعتر عمل میکند. یک لیست پیوندی دوطرفه میتواند به اولین و آخرین عنصرش سریعتر از ArrayList دسترسی داشته باشد. این دقیقاً همان حالتی است که LinkedList را بهتر از ArrayList میکند.
اگر برنامهی شما به یک پشتهی LIFO (Last In, First Out) یا یک صف انتظار FIFO (First In, First Out) نیاز دارد و از هیچ متد دیگر
Listاستفاده نمیکند،LinkedListانتخاب بهتری است. البتهArrayDequeهم گزینهی جالبی است که البته مقدار null را نمیپذیرد.
از طرف دیگر، اگر قصد دارید عناصر لیست را پیمایش کنید یا بهصورت تصادفی با ایندکس به آنها دسترسی داشته باشید، ArrayList بهترین انتخاب شماست.
برای بحث تفصیلیتر دربارهی تفاوتهای ArrayList و LinkedList به انتهای این فصل مراجعه کنید: انتخاب پیادهسازی مناسب بین ArrayList و LinkedList.
رابطهی List چندین متد مرتبط با ایندکس را به رابطهی Collection اضافه میکند.
add(index, element): شیء مورد نظر را در ایندکس مشخصشده درج میکند و ایندکس سایر عناصر را بهروز میکندget(index): شیء موجود در ایندکس مورد نظر را برمیگرداندset(index, element): عنصر موجود در ایندکس مشخصشده را با عنصر جدید جایگزین میکندremove(index): عنصر موجود در ایندکس مشخصشده را حذف میکند و ایندکس سایر عناصر را بهروز میکندفراخوانی این متدها فقط با ایندکسهای معتبر امکانپذیر است. اگر ایندکس نامعتبر باشد، خطای IndexOutOfBoundsException پرتاب میشود.
متدهای indexOf(element) و lastIndexOf(element) ایندکس عنصر مورد نظر در لیست را برمیگردانند. اگر عنصر پیدا نشود، مقدار -1 برگردانده میشود.
subList(start, end) یک لیست شامل عناصر بین ایندکسهای start و end - 1 را برمیگرداند. اگر ایندکسها نامعتبر باشند، خطای IndexOutOfBoundsException پرتاب میشود.
لیست برگشتی یک ویو (view) روی لیست اصلی است. بنابراین هرگونه تغییر روی زیرلیست، روی لیست اصلی اثر میگذارد و بالعکس.
مثلاً میتوانید بخشی از محتوای یک لیست را با الگوی زیر پاک کنید:
خروجی این کد به شکل زیر است:
[0, 1, 2, 3, 4, 5]
[0, 1, 5]
آخرین الگوی مربوط به لیستها، درج یک کلکشن در یک ایندکس مشخص است: addAll(int index, Collection collection).
خروجی این کد به شکل زیر است:
Strings: [0, 1, 5]
To be inserted: [2, 3, 4]
Inserting at index 2
Strings: [0, 1, 2, 3, 4, 5]
یک لیست عناصرش را در ترتیب مشخصی نگه میدارد. این تفاوت اصلی لیست با یک کلکشن ساده است. بنابراین مرتبسازی عناصر یک لیست موضوعی معنادار است. به همین دلیل متد sort() در JDK 8 به رابطهی List اضافه شد.
در Java SE 7 و نسخههای قبلی، برای مرتبسازی عناصر List خود باید Collections.sort() را فراخوانی میکردید و لیست را بهعنوان آرگومان و در صورت نیاز یک Comparator هم ارسال میکردید.
از Java SE 8 به بعد میتوانید مستقیماً sort() را روی لیست فراخوانی کنید و Comparator را بهعنوان آرگومان ارسال کنید. هیچ نسخهای از این متد بدون آرگومان وجود ندارد. فراخوانی آن با comparator برابر null فرض میکند که عناصر List شما رابطهی Comparable را پیادهسازی کردهاند. اگر اینطور نباشد، خطای ClassCastException دریافت خواهید کرد.
اگر از فراخوانی متدها با آرگومان null خوشتان نمیآید (و حق با شماست!)، میتوانید بهجای آن از Comparator.naturalOrder() استفاده کنید تا به همان نتیجه برسید.
رابطهی List یک روش اضافه برای پیمایش عناصر ارائه میدهد: ListIterator. میتوانید این iterator را با فراخوانی listIterator() دریافت کنید. این متد را میتوان بدون آرگومان یا با یک ایندکس عددی فراخوانی کرد. در حالت دوم، پیمایش از همان ایندکس شروع میشود.
رابطهی ListIterator رابطهی Iterator معمولی را extends میکند و چند متد به آن اضافه مینماید:
hasPrevious() و previous(): برای پیمایش به ترتیب نزولی بهجای صعودیnextIndex() و previousIndex(): برای دریافت ایندکس عنصری که توسط فراخوانی بعدی next() یا previous() برگردانده میشودadd(element): درج عنصر در لیست. عنصر دقیقاً قبل از عنصری که فراخوانی بعدی next() برمیگرداند، درج میشود. اگر لیست خالی باشد، عنصر بهسادگی اضافه میشود. فراخوانی بعدی previous() عنصر درجشده را برمیگرداند. فراخوانی بعدی next() تحت تأثیر قرار نمیگیرد.set(element): بهروزرسانی آخرین عنصر برگشتی توسط next() یا previous(). اگر هیچکدام از این متدها فراخوانی نشده باشند، خطای IllegalStateException پرتاب میشود.بیایید عملکرد متد set() را در عمل ببینیم:
خروجی این کد:
numbers = [one, 2, three]
میتوانید با الگوی زیر لیستها ایجاد کنید و عناصر را به آنها اضافه کنید. در مثالهای بعدی الگوهای بیشتری خواهید دید.
خروجی کد بالا:
Fruits: [apple, banana, cherry, date]
لیستها دسترسی مستقیم به اولین و آخرین عنصرشان را فراهم میکنند.
خروجی کد بالا:
First element: apple
Last element: date
Adding apricot at the beginning of the list
Adding mango at the end of the list
First element: apricot
Last element: mango
لیستها با استفاده از ایندکس به عناصرشان دسترسی میدهند. مثال زیر را ببینید.
خروجی کد بالا:
Element at index 0: apple
Element at index 1: banana
Last element: date
After inserting blueberry at index 1: [apple, blueberry, banana, cherry, date]
After replacing index 2 with blackberry: [apple, blueberry, blackberry, cherry, date]
اگر عنصر مورد نظر چندین بار در لیست وجود داشته باشد، میتوانید با الگوی زیر همهی آنها را پیدا کنید.
خروجی کد بالا:
First banana is at index 1
Next banana is at index 3
Next banana is at index 4
No more banana
میتوانید ایندکس یک عنصر مشخص در لیست را پیدا کنید، همانطور که در مثال زیر نشان داده شده است.
خروجی کد بالا:
Index of 'cherry': 2
Index of 'grape' (not found): -1
After removals: [banana, cherry, date]
میتوانید یک زیرلیست از یک لیست دریافت کنید. توجه کنید که این زیرلیست یک ویوی قابل تغییر روی لیست اصلی است.
خروجی کد بالا:
Sublist (indices 1-3): [banana, cherry, date]
Middle fruits: [banana, cherry, date, apricot]
A sublist is a modifiable view on the orginal list
Fruits: [apple, banana, cherry, date, apricot]
Fruits after clearing the sublist: [apple]
میتوانید با ارسال یک Comparator لیست را مرتب کنید.
خروجی کد بالا:
Fruits, sorted ascending order: [apple, cherry, date, peach, plum]
Fruits, sorted descending order: [plum, peach, date, cherry, apple]
میتوانید ترتیب عناصر لیست را معکوس کنید.
خروجی کد بالا. توجه کنید آنچه List.reversed() برمیگرداند یک ویو روی لیست اصلی است.
Original order: [peach, plum, cherry, apple, date]
Reverse order: [date, apple, cherry, plum, peach]
Adding an apricot at index 2
Original order: [peach, plum, apricot, cherry, apple, date]
Reverse order: [date, apple, cherry, apricot, plum, peach]
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://dev.java/learn/