سؤال

هل لدى أي شخص قاعدة أساسية جيدة للاختيار بين التطبيقات المختلفة لواجهات Java Collection مثل القائمة أو الخريطة أو المجموعة؟

على سبيل المثال، بشكل عام، لماذا أو في أي الحالات أفضّل استخدام Vector أو ArrayList أو Hashtable أو HashMap؟

هل كانت مفيدة؟

المحلول

لقد اتخذت دائمًا هذه القرارات على أساس كل حالة على حدة، اعتمادًا على حالة الاستخدام، مثل:

  • هل أحتاج إلى بقاء الأمر؟
  • هل سيكون لدي مفتاح/قيم فارغة؟الأغبياء؟
  • هل سيتم الوصول إليه من خلال عدة سلاسل رسائل
  • هل أحتاج إلى زوج المفتاح/القيمة
  • هل سأحتاج إلى وصول عشوائي؟

وبعد ذلك أقوم بإصدار الطبعة الخامسة المفيدة جافا باختصار وقارن الخيارات العشرين تقريبًا أو نحو ذلك.يحتوي على جداول صغيرة لطيفة في الفصل الخامس لمساعدة الشخص على معرفة ما هو مناسب.

حسنًا، ربما إذا كنت أعلم أن قائمة ArrayList أو HashSet البسيطة ستفي بالغرض، فلن أبحث عن كل شيء.؛) ولكن إذا كان هناك أي شيء معقد عن بعد فيما يتعلق باستخدامي المقصود، فأنت تراهن أنني موجود في الكتاب.راجع للشغل، على الرغم من أن Vector من المفترض أن يكون "قبعة قديمة" - لم أستخدمها منذ سنوات.

نصائح أخرى

تعجبني حقًا ورقة الغش هذه من سيرجي كوفالتشوك دخول بلوق:

Java Map/Collection Cheat Sheet

كان المخطط الأكثر تفصيلاً هو المخطط الانسيابي الخاص بـ Alexander Zagniotov، لكنه للأسف غير متصل بالإنترنت.

سأفترض أنك تعرف الفرق بين القائمة والتعيين والخريطة من الإجابات المذكورة أعلاه.لماذا تختار بين فئات التنفيذ الخاصة بهم هو شيء آخر.على سبيل المثال:

قائمة:

  1. ArrayList سريع في الاسترداد، ولكنه بطيء في الإدخال.إنه جيد للتنفيذ الذي يقرأ كثيرًا ولكنه لا يُدرج/يزيل الكثير.فهو يحتفظ ببياناته في كتلة واحدة متواصلة من الذاكرة، لذلك في كل مرة يحتاج فيها إلى التوسيع، فإنه ينسخ المصفوفة بأكملها.
  2. قائمة مرتبطة بطيء في الاسترداد، ولكنه سريع في الإدخال.إنه جيد للتطبيق الذي يُدرج/يزيل الكثير ولكنه لا يقرأ كثيرًا.لا يحتفظ بالمصفوفة بأكملها في كتلة واحدة مستمرة من الذاكرة.

تعيين:

  1. HashSet لا يضمن ترتيب التكرار، وبالتالي فهو الأسرع بين المجموعات.إنه ذو حمل مرتفع وأبطأ من ArrayList، لذا لا يجب استخدامه إلا لكمية كبيرة من البيانات عندما تصبح سرعة التجزئة عاملاً.
  2. TreeSet يحافظ على البيانات مرتبة، وبالتالي فهو أبطأ من HashSet.

خريطة: أداء وسلوك HashMap وTreeMap متوازيان مع تطبيقات المجموعة.

لا ينبغي استخدام Vector وHashtable.وهي عبارة عن تطبيقات متزامنة، قبل إصدار التسلسل الهرمي للمجموعة الجديد، وبالتالي تكون بطيئة.إذا كانت المزامنة مطلوبة، استخدم Collections.synchronizedCollection().

من الناحية النظرية هناك مفيدة كبير أوه المقايضات، ولكن في الممارسة العملية، لا أهمية لها على الإطلاق.

في معايير العالم الحقيقي، ArrayList يتفوق LinkedList حتى مع القوائم الكبيرة ومع عمليات مثل "الكثير من الإدراج بالقرب من الأمام". يتجاهل الأكاديميون حقيقة أن الخوارزميات الحقيقية لها عوامل ثابتة يمكن أن تطغى على المنحنى المقارب.على سبيل المثال، تتطلب القوائم المرتبطة تخصيص كائن إضافي لكل عقدة، مما يعني تباطؤًا في إنشاء العقدة وخصائص وصول إلى الذاكرة أسوأ بكثير.

قاعدتي هي:

  1. ابدأ دائمًا بـ ArrayList وHashSet وHashMap (أي.ليست LinkedList أو TreeMap).
  2. يجب أن تكون إعلانات النوع دائمًا واجهة (على سبيل المثال.قائمة، تعيين، خريطة) لذا إذا أثبت ملف التعريف أو مراجعة التعليمات البرمجية خلاف ذلك، فيمكنك تغيير التنفيذ دون كسر أي شيء.

بخصوص سؤالك الأول...

تخدم القائمة والخريطة والإعداد أغراضًا مختلفة.أقترح القراءة عن Java Collections Framework على http://java.sun.com/docs/books/tutorial/collections/interfaces/index.html.

لكي نكون أكثر واقعية قليلاً:

  • استخدم القائمة إذا كنت بحاجة إلى بنية بيانات تشبه المصفوفة وتحتاج إلى التكرار على العناصر
  • استخدم الخريطة إذا كنت بحاجة إلى شيء مثل القاموس
  • استخدم مجموعة إذا كنت تحتاج فقط إلى تحديد ما إذا كان هناك شيء ينتمي إلى المجموعة أم لا.

بخصوص سؤالك الثاني...

الفرق الرئيسي بين Vector و ArrayList هو أن الأول متزامن، والأخير غير متزامن.يمكنك قراءة المزيد عن المزامنة في جافا التزامن في الممارسة العملية.

الفرق بين Hashtable (لاحظ أن T ليس حرفًا كبيرًا) وHashMap مشابه، الأول متزامن، والأخير غير متزامن.

أود أن أقول أنه لا توجد قاعدة أساسية لتفضيل تطبيق أو آخر، فالأمر يعتمد حقًا على احتياجاتك.

بالنسبة للخيارات غير المصنفة، سيكون الاختيار الأفضل، أكثر من تسع مرات من أصل عشرة، هو:ArrayList، HashMap، HashSet.

تتم مزامنة Vector وHashtable وبالتالي قد يكونا أبطأ قليلاً.من النادر أن ترغب في تطبيقات متزامنة، وعندما تفعل ذلك، فإن واجهاتها ليست غنية بما يكفي لتكون مزامنتها مفيدة.في حالة Map، يضيف ConcurrentMap عمليات إضافية لجعل الواجهة مفيدة.يعد ConcurrentHashMap تطبيقًا جيدًا لـ ConcurrentMap.

LinkedList ليست فكرة جيدة على الإطلاق.حتى إذا كنت تقوم بالكثير من عمليات الإدراج والإزالة، إذا كنت تستخدم فهرسًا للإشارة إلى الموضع، فإن ذلك يتطلب التكرار عبر القائمة للعثور على العقدة الصحيحة.ArrayList دائمًا ما يكون أسرع.

بالنسبة إلى Map وSet، ستكون متغيرات التجزئة أسرع من الشجرة/الفرز.تميل خوارزميات التجزئة إلى الحصول على أداء O(1)، بينما ستكون الأشجار O(log n).

تسمح القوائم بالعناصر المكررة، بينما تسمح المجموعات بمثيل واحد فقط.

سأستخدم الخريطة عندما أحتاج إلى إجراء بحث.

بالنسبة للتطبيقات المحددة، هناك اختلافات في الخرائط والمجموعات تحافظ على الترتيب، ولكن الأمر يعتمد إلى حد كبير على السرعة.سأميل إلى استخدام ArrayList للقوائم الصغيرة إلى حد معقول وHashSet للمجموعات الصغيرة إلى حد معقول، ولكن هناك العديد من التطبيقات (بما في ذلك أي تطبيقات تكتبها بنفسك).HashMap شائع جدًا في الخرائط.أي شيء أكثر من "صغير إلى حد معقول" وعليك أن تبدأ في القلق بشأن الذاكرة، لذا سيكون ذلك أكثر تحديدًا من الناحية الخوارزمية.

هذه الصفحة لديه الكثير من الصور المتحركة بالإضافة إلى نموذج اختبار التعليمات البرمجية LinkedList vs.ArrayList إذا كنت مهتمًا بالأرقام الصلبة.

يحرر: آمل أن توضح الروابط التالية كيف أن هذه الأشياء هي في الواقع مجرد عناصر في صندوق الأدوات، عليك فقط التفكير في احتياجاتك:راجع إصدارات مجموعات كومنز خريطة, قائمة و تعيين.

كما هو مقترح في الإجابات الأخرى، هناك سيناريوهات مختلفة لاستخدام المجموعة الصحيحة اعتمادًا على حالة الاستخدام.سأذكر بعض النقاط،

قائمة الصفيف:

  • في معظم الحالات، تحتاج فقط إلى التخزين أو التكرار من خلال "مجموعة من الأشياء" ثم التكرار من خلالها لاحقًا.التكرار أسرع لأنه يعتمد على الفهرس.
  • عندما تقوم بإنشاء ArrayList، يتم تخصيص مقدار ثابت من الذاكرة لها وبمجرد تجاوزها، تقوم بنسخ المصفوفة بأكملها

قائمة مرتبطة:

  • يستخدم قائمة مرتبطة بشكل مضاعف لذا ستكون عملية الإدراج والحذف سريعة لأنها ستضيف أو تزيل عقدة فقط.
  • عملية الاسترداد بطيئة حيث سيتعين عليها التكرار عبر العقد.

مجموعة التجزئة:

  • اتخاذ قرارات نعم أو لا أخرى بشأن عنصر ما، على سبيل المثال."هل العنصر كلمة باللغة الإنجليزية" ، "هل العنصر في قاعدة البيانات؟" ، "هل العنصر في هذه الفئة؟" إلخ.

  • تذكر "العناصر التي قمت بمعالجتها بالفعل"، على سبيل المثال.عند القيام بالزحف على شبكة الإنترنت؛

خريطة التجزئة:

  • تستخدم في الحالات التي تحتاج فيها إلى قول "بالنسبة لـ X معين، ما هو Y"؟غالبًا ما يكون مفيدًا لتنفيذ ذاكرة التخزين المؤقت أو الفهارس في الذاكرة، أي أزواج القيمة الرئيسية على سبيل المثال:بالنسبة لمعرف مستخدم معين، ما هو اسم المستخدم/كائن المستخدم المخزن مؤقتًا؟.
  • استخدم دائمًا HashMap لإجراء البحث.

تتم مزامنة Vector وHashtable وبالتالي تكون أبطأ قليلاً، وإذا كانت المزامنة مطلوبة، فاستخدم Collections.synchronizedCollection().يفحص هذا للمجموعات المصنفة.نأمل أن يكون هذا هابلد.

لقد وجدت أن تفكير بروس إيكل في جافا مفيد جدًا.إنه يقارن المجموعات المختلفة بشكل جيد للغاية.اعتدت أن أحتفظ بالرسم التخطيطي الذي نشره والذي يوضح تسلسل الميراث على حائطي المكعب كمرجع سريع.شيء واحد أقترح عليك فعله هو أن تضع في اعتبارك سلامة الخيط.الأداء يعني عادة أن الخيط غير آمن.

حسنا، ذلك يعتمد على ما تحتاجه.المبادئ التوجيهية العامة هي:

قائمة عبارة عن مجموعة يتم فيها الاحتفاظ بالبيانات حسب ترتيب الإدراج ويحصل كل عنصر على فهرس.

تعيين عبارة عن حقيبة من العناصر بدون تكرار (إذا قمت بإعادة إدراج نفس العنصر، فلن تتم إضافته).البيانات ليس لديها فكرة النظام.

خريطة يمكنك الوصول إلى عناصر البيانات الخاصة بك وكتابتها من خلال مفتاحها، والذي يمكن أن يكون أي كائن محتمل.

enter image description hereالإسناد: https://stackoverflow.com/a/21974362/2811258

لمزيد من المعلومات حول مجموعات جافا، تحقق من هذه المقالة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top