لماذا لا تحصل على java.util.Set (فهرس int)؟



7 Answers

في الواقع هذا سؤال متكرر عند كتابة تطبيقات JavaEE التي تستخدم التعيين Object-Relational (على سبيل المثال مع Hibernate) ؛ ومن جميع الأشخاص الذين أجابوا هنا ، كان أندرياس بيترسون هو الشخص الوحيد الذي فهم القضية الحقيقية وعرض الإجابة الصحيحة لها: جافا تفتقد إلى قائمة فريدة! (أو يمكنك أيضًا الاتصال به OrderedSet أو IndexedSet).

ذكر Maxwing حالة الاستخدام هذه (التي تحتاج فيها إلى بيانات مرتبة و فريدة) واقترح على SortedSet ، لكن هذا ليس ما يحتاجه Marty Pitt فعلاً.

هذا "IndexedSet" ليس هو نفسه لـ SortedSet - في SortedSet يتم فرز العناصر باستخدام المقارنة (أو باستخدام الطلب "الطبيعي" الخاص به).

ولكن بدلاً من ذلك ، يكون أقرب إلى LinkedHashSet (الذي اقترحه الآخرون أيضًا) ، أو أكثر إلى (AroundListSet) (لأنه غير موجود أيضًا) ، لأنه يضمن إرجاع العناصر بنفس الترتيب الذي تم إدخالها به.

لكن LinkedHashSet هو تطبيق ، وليس واجهة! ما هو مطلوب هو واجهة IndexedSet (أو ListSet ، أو OrderedSet ، أو UniqueList)! سيسمح هذا للمبرمج بتحديد أنه يحتاج إلى مجموعة من العناصر التي لها ترتيب معين وبدون تكرار ، ثم قم بتشكيله بأي تنفيذ (على سبيل المثال ، تنفيذ يوفره Hibernate).

نظرًا لأن JDK مفتوح المصدر ، فربما يتم تضمين هذه الواجهة أخيراً في Java 7 ...

Question

أنا متأكد من أن هناك سببًا جيدًا ، ولكن هل يمكن لشخص ما أن يفسر سبب عدم حصول واجهة java.util.Set get(int Index) ، أو أي طريقة مشابهة get() ؟

يبدو أن المجموعات رائعة لوضع الأشياء ، ولكن لا يمكنني العثور على طريقة أنيقة لاسترداد عنصر واحد منه.

إذا كنت أعرف أنني أريد العنصر الأول ، set.iterator().next() استخدام set.iterator().next() ، ولكن بخلاف ذلك ، يبدو أنه يتوجب علي إرسال مجموعة إلى مصفوفة لاسترداد عنصر في فهرس معين؟

ما هي الطرق المناسبة لاسترداد البيانات من مجموعة؟ (بخلاف استخدام مكرر)

أنا متأكد من حقيقة أن استبعاده من واجهة برمجة التطبيقات يعني وجود سبب وجيه لعدم القيام بذلك - هل يمكن لأي شخص أن ينيرني؟

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

ومع ذلك ، فإن السؤال أكثر صلاحية بدون السيناريو ، لأنه لا يزال أكثر تركيزًا:

ما الفرق بين المجموعة والقائمة .

شكرا للجميع على إجابات رائعة أدناه.




بعض هياكل البيانات مفقودة من مجموعات جافا القياسية.

حقيبة (مثل المجموعة ولكن يمكن أن تحتوي على عناصر عدة مرات)

UniqueList (قائمة مرتبة ، يمكن أن تحتوي على كل عنصر مرة واحدة فقط)

يبدو أنك ستحتاج إلى أخصائي في هذه الحالة

إذا كنت تحتاج إلى هياكل بيانات مرنة ، فقد تكون مهتمًا بمجموعات Google




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

  • يمكن الوصول إلى بنية بيانات المصفوفة عبر الفهرس مع تعقيد زمن O(1) لتحقيق عملية get(int index) .
  • يمكن أيضًا الوصول إلى بنية بيانات LinkedList عبر الفهرس ، ولكن مع تعقيد زمن O(n) لتحقيق عملية get(int index) .

في Java ، يتم تنفيذ ArrayList باستخدام بنية بيانات Array .

على الرغم من أنه يمكن عادةً تنفيذ بنية بيانات المجموعة عبر بنية بيانات HashTable / HashMap أو BalancedTree ، وذلك للكشف السريع عما إذا كان العنصر موجودًا وإضافة عنصر غير موجود ، عادةً ما تكون المجموعة التي تم تنفيذها بشكل جيد قادرة على تحقيق O(1) تعقيد زمني contains العملية. في Java ، يعد HashSet أكثر استخدامًا شائعًا لتطبيق Set ، ويتم تنفيذه عن طريق استدعاء HashMap API ، ويتم تطبيق HashMap باستخدام تسلسل منفصل مع القوائم المرتبطة (مجموعة من Array و LinkedList ).

بما أن المجموعة يمكن تنفيذها عبر بنية بيانات مختلفة ، فلا يوجد طريقة get(int index) لها.




السبب في أن واجهة Set لا تحتوي على استدعاء من نوع فهرس أو حتى شيء أكثر أساسية ، مثل first () أو last () ، لأنه عملية غامضة ، وبالتالي عملية خطيرة محتملة. إذا كانت إحدى الطرق تقوم بإرجاع مجموعة (Set) ، وقمت بالاتصال ، فقم بتعبير أول () طريقة ، ما هي النتيجة المتوقعة ، على اعتبار أن مجموعة عامة لا تقدم أي ضمانات بشأن الطلب؟ قد يختلف الكائن الناتج تمامًا بين كل استدعاء لهذه الطريقة ، أو قد لا يؤدي إلى تهدئتك وإدراكك إلى إحساس زائف بالأمان ، إلى أن تغير المكتبة التي تستخدمها التغييرات في التنفيذ وتجد الآن أن جميع فواصل الشفرة الخاصة بك لا يوجد سبب معين.

الاقتراحات حول الحلول المدرجة هنا جيدة. إذا كنت بحاجة إلى الوصول المفهرسة ، فاستخدم قائمة. كن حذرًا عند استخدام المتكررات أو إلى التسجيل باستخدام مجموعة عامة ، لأن (أ) لا يوجد ضمان على الطلب و (ب) لا يوجد ضمان بأن الترتيب لن يتغير مع الدعوات اللاحقة أو مع التطبيقات الأساسية المختلفة. إذا كنت تحتاج إلى شيء ما بين ، فإن SortedSet أو LinkedHashSet هو ما تريده.

/ / أنا أتمنى لو أن واجهة التعيين كانت تحتوي على عنصر الحصول على عشوائي على الرغم من ذلك.




السبب الوحيد الذي يمكنني التفكير فيه باستخدام مؤشر رقمي في مجموعة سيكون للتكرار. لذلك ، استخدم

for(A a : set) { 
   visit(a); 
}



إذا كنت لا تمانع في فرز المجموعة ، فقد تكون مهتمًا بإلقاء نظرة على مشروع indexed-tree-map .

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




إذا كنت ستفعل الكثير من الوصول العشوائي عن طريق الفهرس في مجموعة ، يمكنك الحصول على عرض مصفوفة لعناصرها:

Object[] arrayView = mySet.toArray();
//do whatever you need with arrayView[i]

هناك نوعان من العيوب الرئيسية على الرغم من:

  1. إنها لا تتسم بالكفاءة في استخدام الذاكرة ، نظرًا لأنه يلزم إنشاء مصفوفة لمجموعة كاملة.
  2. إذا تم تعديل المجموعة ، يصبح العرض قديمًا.



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

  1. إذا كنت بحاجة إلى البيانات المطلوبة ، فاستخدم قائمة
  2. إذا كنت بحاجة إلى بيانات فريدة ، فاستخدم مجموعة
  3. إذا كنت بحاجة إلى كليهما ، فاستخدم إما: SortedSet (للبيانات المطلوبة بواسطة المقارنة) أو OrderedSet / UniqueList (للبيانات المطلوبة بواسطة الإدراج). لسوء الحظ ، لا يحتوي Java API بعد على OrderedSet / UniqueList.

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




Related