Java Deque عبارة عن بنية بيانات تجمع بين قائمة انتظار عادية ومكدس. يمكنك إضافة وإزالة العناصر إلى الرأس وذيل Deque. في قائمة الانتظار "التقليدية"، يمكنك إضافة عناصر إلى ذيل السطر (بعد العنصر الأخير) وإزالة العناصر من رأس قائمة الانتظار. يُطلق على هذا المبدأ اسم "الوارد أولاً يخرج أولاً" (FIFO) ويعمل مثل أي خط معتاد من العملاء في الحياة الواقعية. في Java، تعتبر قائمة الانتظار واجهة، وهي جزء من Collections Framework. هناك أيضًا بنية بيانات مهمة تسمى Stack، وهي قائمة تعمل مع العناصر بمبدأ عكسي تمامًا، LIFO - آخر ما يدخل أولاً يخرج أولاً. إنه يشبه كومة من اللوحات، ولا يمكن إضافة أو إزالة إلا من الأعلى.
قائمة الانتظار مقابل Deque
Deque هو نوع غريب من قائمة الانتظار: يمكنك إضافة عناصر جديدة إلى كل من الذيل ورأس السطر. نفس القصة مع الإزالة: يمكنك إزالة العنصر الأخير أو الأول من هذه البنية. ومن ثم، يبدو أنه مزيج من Stack وQueue. الاسم "Deque" يعني "قائمة الانتظار ذات النهاية المزدوجة". يتم نطق كلمة "Deque" مثل "مجموعة" من البطاقات وأنت تعرف ماذا؟ إنها تشبه إلى حد ما مجموعة أوراق اللعب الحقيقية: يمكنك أن تأخذ بطاقة من أسفل أو أعلى هذه المجموعة. هل تريد إضافة أو إزالة عناصر من جانبي بعض البنية الخطية؟ استخدم ديك. يدعمه Java 8 أو أي إصدار آخر تقريبًا. تخيل لبنة ليغو نموذجية و"أبراج" ذات عمود واحد مصنوعة من الطوب. يمكنك إضافة لبنة جديدة إلى أعلى البرج أو إلى أسفله. يمكنك أيضًا إزالة الطوب من كلا الجانبين. لدينا هنا مثال: نضيف كل الطوب الأصفر إلى الأعلى وكل الطوب الأحمر إلى الأسفل. سنوضح هذا المثال باستخدام كود Java قريبًا. لذلك يمكنك وضع قائمة الانتظار وإلغاء قائمة الانتظار من طرفي Java Deque، وهذا يعني أنه يمكنك استخدام Deque كقائمة انتظار ومكدس. اقرأ عن Stack in Java: Java Stack 101: الخوض في فئة Stack
اقرأ عن قائمة الانتظار في Java: Java Queue Interface وتطبيقاتها
مميزات ديك
Deque في Java عبارة عن واجهة توفر التطبيقات دعمًا لمصفوفة يمكن تغيير حجمها. لذلك لديك مجموعة من السعة الخالية من القيود ويمكنك إضافة عناصر جديدة وفقًا لاحتياجاتك.
لا يدعم Deque الوصول المتزامن عبر سلاسل رسائل متعددة
Deque ليس آمنًا لمؤشر الترابط في حالة غياب المزامنة الخارجية.
لا يوجد عناصر فارغة مسموح بها في مجموعة deque.
إعلان واجهة Deque Java
publicinterfaceDeque<E>extendsQueue<E>
طرق جافا Deque
java.util.Deque هي واجهة تعمل على توسيع واجهة Java Queue Interface وتمثل قائمة انتظار مزدوجة النهاية. لذلك يمكنك استخدام جميع أساليب Java Queue أثناء العمل مع Deque. على الرغم من أن Deque لا يعمل على توسيع واجهة Stack، إلا أن واجهة Deque تحدد الأساليب التي تمكنك من القيام بعمليات المكدس النموذجية مثل الدفع والنظرة الخاطفة والبوب .
إضافة منطقية (عنصر) تضيف عنصرًا إلى ذيل Deque. يُرجع صحيحًا عند النجاح، ويطرح استثناء IllegalStateException في حالة عدم توفر مساحة حاليًا.
يضيف addFirst(element) عنصرًا إلى رأس Deque.
يضيف addLast(element) عنصرًا إلى ذيل Deque.
يضيف العرض (العنصر) عنصرًا إلى الذيل ويعيد قيمة منطقية لتوضيح ما إذا كان الإدراج ناجحًا.
يضيف OfferFirst(element) عنصرًا إلى الرأس ويعيد قيمة منطقية لتوضيح ما إذا كان الإدراج ناجحًا.
يضيف OfferLast(element) عنصرًا إلى الذيل ويعيد قيمة منطقية لتوضيح ما إذا كان الإدراج ناجحًا.
iterator() يُرجع مكررًا لـ deque.
يُرجع التابعscendingIterator() مُكرِّرًا له ترتيب عكسي لهذا deque.
يضيف Push(element) عنصرًا إلى الرأس.
يقوم pop(element) بإزالة عنصر من الرأس وإعادته.
RemoveFirst() يزيل العنصر الموجود في الرأس.
RemoveLast() يزيل العنصر الموجود في الذيل.
يقوم Poll() باسترداد وإزالة رأس قائمة الانتظار التي يمثلها هذا deque (بمعنى آخر، العنصر الأول من هذا deque)، أو يُرجع قيمة فارغة إذا كان هذا deque فارغًا.
يقوم pollFirst() باسترداد وإزالة العنصر الأول من مجموعة deque هذه، أو إرجاع قيمة فارغة إذا كانت مجموعة deque هذه فارغة.
يقوم pollLast() باسترداد وإزالة العنصر الأخير من مجموعة deque هذه، أو إرجاع قيمة فارغة إذا كانت مجموعة deque هذه فارغة.
تسترد الدالة peek() رأس قائمة الانتظار التي يمثلها هذا deque (بمعنى آخر، العنصر الأول من هذا deque)، ولكنها لا تزيله، أو ترجع قيمة فارغة إذا كانت deque فارغة.
يسترد peekFirst() العنصر الأول من deque هذا، لكنه لا يزيله، أو يُرجع قيمة فارغة إذا كان deque فارغًا.
يسترد peekLast () العنصر الأخير من deque هذا، لكنه لا يزيله، أو يُرجع قيمة فارغة إذا كان deque فارغًا.
هنا في الجدول أدناه يتم تقسيم جميع الطرق حسب المجموعات. كما ترون، هناك العديد من الطرق المختلفة لإضافة عنصر وإزالته. على سبيل المثال، يقوم كل من RemoveFirst() وpop() بإزالة العنصر الأول من deque. والثاني "جاء" من المكدس. هذا يعني أنه إذا كنت تستخدم ArrayDeque كمكدس فقط، فاستخدم pop() للإزالة، وpush() للإضافة، وpeek() للفحص. وهذا يجعل التعليمات البرمجية الخاصة بك أكثر منطقية للمطورين الآخرين.
العنصر الأول (الرأس)
العنصر الأخير (الذيل)
عملية
يلقي استثناء
قيمة خاصة
يلقي استثناء
قيمة خاصة
إدراج
addFirst(e)/دفع(e)
العرض الأول (هـ)
إضافةالأخير(ه)
العرض الأخير ()
يزيل
إزالة الأول ()/البوب ()
إستطلاع أول ()
إزالة الأخير ()
آخر استطلاع ()
يفحص
الحصول على الأول ()
نظرة خاطفة ()/نظرة خاطفة ()
انه شهر مميز لصنع الابطال()
نظرة خاطفة ()
تنفيذات Deque
Java Deque عبارة عن واجهة ولها تطبيقات في Java Collections API:
java.util.LinkedList // تنفيذ القائمة وDeque
java.util.ArrayDeque // تنفيذ Deque، مكتبة Java
تستخدم فئة LinkedList قائمة مرتبطة بشكل مزدوج داخليًا لتكوين قائمة انتظار أو قائمة انتظار. تقوم فئة ArrayDeque بتخزين العناصر داخليًا في المصفوفة. إذا تجاوز عدد العناصر حجم المصفوفة، فسيتم تخصيص مصفوفة جديدة، ويتم نقل جميع العناصر إليها. وهذا يعني أن ArrayDeque ينمو حسب الاحتياجات.
فئة ArrayDeque
فئة ArrayDeque <E> عبارة عن قائمة انتظار عامة ذات اتجاهين، ترث الوظائف من فئة AbstractCollection وتستخدم واجهة Deque. يوفر ArrayDeque إمكانية استخدام المصفوفة deque والمصفوفة القابلة لتغيير الحجم. في البداية، تتم تهيئة المصفوفة بالحجم 16. ويتم تنفيذها كقائمة انتظار ثنائية الاتجاه، حيث تدعم مؤشرين، وهما الرأس والذيل. إنه يرث فئة AbstractCollection وينفذ واجهة Deque . النقاط المهمة حول فئة ArrayDeque هي:
يمكنك إضافة أو إزالة عناصر من الذيل ورأس ArrayDeque
غير مسموح بالعناصر الفارغة
ArrayDeque ليس مؤشر ترابط آمن، في غياب المزامنة الخارجية.
ArrayDeque ليس لديه قيود على السعة.
ArrayDeque فئة المنشئين
يقوم ArrayDeque() بإنشاء قائمة انتظار فارغة.
يقوم ArrayDeque (مجموعة <? Extends E>) بإنشاء قائمة انتظار مليئة بعناصر مجموعة المجموعة.
يقوم ArrayDeque (سعة int) بإنشاء قائمة انتظار ذات سعة أولية . إذا لم تحدد السعة الأولية، فستكون السعة الافتراضية هي 16.
مثال Java Deque - ArrayDeque
تذكر مثال برج ليغو من بداية المقال؟ لنقم بإنشاء فصل دراسي لبناء أبراج ذات عمود واحد مصنوعة من طوب الليغو. يمكن أن يكون الطوب أحمر أو أصفر أو أزرق. قاعدة بناء البرج لدينا: نضع الطوب الأحمر في الأسفل والطوب الأصفر في الأعلى. مثال كبير لـ Java Deque
//enum with colorspublicenumColor{
RED, YELLOW, BLUE;}//class for the standard Lego Brick. You can connect or disconnect the Brick, it has colorpublicclassLegoBrick{Color color;boolean isConnected;publicvoidconnect(){System.out.println("This brick is connected");this.isConnected =true;}publicvoiddisconnect(){System.out.println("Disconnected");
isConnected =false;}publicLegoBrick(Color color,boolean isConnected){this.color = color;this.isConnected = isConnected;}publicColorgetColor(){return color;}publicbooleanisConnected(){return isConnected;}@OverridepublicStringtoString(){return"LegoBrick{"+"color="+ color +", isConnected="+ isConnected +'}';}}
هنا فئة البرج لدينا. نبدأ البرج. يعتمد البرج المبدئي على كمية اللون الأحمر والأصفر. يمكننا إضافة الطوب إلى البرج أو إزالته. نضيف الطوب إلى الأعلى إذا كان أصفر ونضيفه إلى الأسفل إذا كان أحمر.
importjava.util.ArrayDeque;publicclassLegoTower{ArrayDeque<LegoBrick> myTower;int quantityOfReds;int quantityOfYellows;publicvoidaddBrickToTower(LegoBrick newLegoBrick){if(newLegoBrick.getColor()==Color.YELLOW){this.myTower.offerLast(newLegoBrick);
quantityOfYellows++;}//we can use addFirst(e)/push(e) instead of offerFirst hereif(newLegoBrick.getColor()==Color.RED){
myTower.offerFirst(newLegoBrick);
quantityOfReds++;}}publicvoid removeBrickFromTower (LegoBrick legoBrick){if(legoBrick.getColor()==Color.YELLOW){this.myTower.removeLast();
quantityOfYellows--;}if(legoBrick.getColor()==Color.RED){
myTower.removeFirst();
quantityOfReds--;}
legoBrick.isConnected =false;}publicLegoTower(int quantityOfReds,int quantityOfYellows){
myTower =newArrayDeque<>();this.quantityOfReds = quantityOfReds;this.quantityOfYellows = quantityOfYellows;for(int i =0; i < quantityOfReds; i++){LegoBrick redLegoBrick =newLegoBrick(Color.RED,false);
myTower.addFirst(redLegoBrick);
redLegoBrick.isConnected =true;}for(int i =0; i < quantityOfYellows; i++){LegoBrick yellowLegoBrick =newLegoBrick(Color.YELLOW,false);
myTower.addLast(yellowLegoBrick);
yellowLegoBrick.isConnected =true;}}publicvoidsetMyTower(ArrayDeque<legobrick> myTower){this.myTower = myTower;}publicvoidsetQuantityOfReds(int quantityOfReds){this.quantityOfReds = quantityOfReds;}publicvoidsetQuantityOfYellows(int quantityOfYellows){this.quantityOfYellows = quantityOfYellows;}@OverridepublicStringtoString(){return"LegoTower{"+"myTower="+ myTower +", quantityOfReds="+ quantityOfReds +", quantityOfYellows="+ quantityOfYellows +'}';}publicvoiddrawTower(){for(LegoBrick i : myTower){System.out.println(i.color);}}}publicclassMain{publicstaticvoidmain(String[] args){LegoBrick legoBrick1 =newLegoBrick(Color.YELLOW,false);
legoBrick1.connect();System.out.println(legoBrick1.toString());
legoBrick1.disconnect();System.out.println(legoBrick1.toString());LegoBrick legoBrick2 =newLegoBrick(Color.YELLOW,false);LegoBrick legoBrick3 =newLegoBrick(Color.RED,false);LegoBrick legoBrick4 =newLegoBrick(Color.RED,false);LegoBrick legoBrick5 =newLegoBrick(Color.YELLOW,false);LegoTower legoTower =newLegoTower(2,5);System.out.println("my Initiated Lego Tower: ");
legoTower.drawTower();
legoTower.addBrickToTower(legoBrick1);
legoTower.addBrickToTower(legoBrick2);
legoTower.addBrickToTower(legoBrick3);
legoTower.addBrickToTower(legoBrick4);
legoTower.addBrickToTower(legoBrick5);System.out.println("My LegoTower after adding some elements: ");
legoTower.drawTower();
legoTower.removeBrickFromTower(legoBrick1);
legoTower.removeBrickFromTower(legoBrick3);System.out.println("We removed one red and one yellow brick:");
legoTower.drawTower();}}
نتيجة تشغيل هذا البرنامج:
my Initiated LegoTower:
RED
RED
YELLOW
YELLOW
YELLOW
YELLOW
YELLOW
My LegoTower after adding some elements:
RED
RED
RED
RED
YELLOW
YELLOW
YELLOW
YELLOW
YELLOW
YELLOW
YELLOW
YELLOW
We removed one red and one yellow brick:
RED
RED
RED
YELLOW
YELLOW
YELLOW
YELLOW
YELLOW
YELLOW
YELLOW
Process finished with exit code 0
انتظر ماذا؟؟ لماذا اللون الأحمر في الأعلى؟ كلا، لا يفعلون ذلك. لقد طبعوا للتو على وحدة التحكم بدءًا من الأول (أسفل) إلى الأخير (أعلى). لذلك، إذا كنت تريد رؤية شيء مثل الصورة مع الطوب أعلاه، فيمكنك تغيير طريقة drawTower لفئة LegoTower. إنها مهمة سهلة للغاية!
قائمة مرتبطة
تحافظ واجهة القائمة على تسلسل إضافة العناصر وتسمح بالوصول إلى العنصر عن طريق الفهرس. Deque عبارة عن قائمة انتظار ثنائية الاتجاه، وهي تدعم إضافة وإزالة العناصر من كلا الجانبين. تُعرف LinkedList بشكل أساسي بتطبيق القائمة، ولكن هذه الفئة أيضًا تنفذ Deque، وتسمح لنا بإنشاء قائمة انتظار ثنائية الاتجاه تتكون من أي كائنات بما في ذلك العناصر الفارغة. LinkedList عبارة عن مجموعة من العناصر. يمكننا رؤيته في مصدر التعليمات البرمجية للفصل، هذه المرة انتبه إلى الحقول: هنا نضيف مثالًا واحدًا، ولكن إذا كنت تريد معرفة المزيد حول LinkedList، فمرحبًا بك في مقالة CodeGym
هذه .
تنفيذ القائمة المرتبطة في جافا، وإضافة وإزالة العناصر. مثال
دعونا نجرب هذه العمليات عمليا. أولاً، تنفيذ Java LinkedList: إنشاء قائمة LinkedList من السلاسل، وإضافة 3 عناصر إليها. ثم قم بإزالة واحدة، ثم قم بإضافة واحدة في المنتصف.
publicclassMyLinkedTest{publicstaticvoidmain(String[] args){String h1 ="my";String h2 ="favorite";String h3 ="book";// LinkedList implementation in JavaLinkedList<string> linkedList =newLinkedList();
linkedList.add(h1);
linkedList.add(h2);
linkedList.add(h3);System.out.println("my list after adding 3 elements:");System.out.println(linkedList);System.out.println("element #2 of my list:");System.out.println(linkedList.get(2));
linkedList.remove(1);System.out.println("my list after removing #1:");System.out.println(linkedList);
linkedList.add(1,"first");System.out.println("my list after adding an element in the middle");System.out.println(linkedList);}
نتيجة تشغيل هذا البرنامج:
my list after adding 3 elements:
[my, favorite, book]
element #2 of my list:
book
my list after removing #1:
[my, book]
my list after adding an element in the middle
[my, first, book]
GO TO FULL VERSION