ما هي أفضل طريقة لإزالة التكرارات في صفيف في جافا ؟
-
21-08-2019 - |
سؤال
لدي مجموعة من الكائنات التي تحتاج إلى إزالة التكرارات/تصفيتها.كنت ذاهبا لمجرد تجاوز يساوي & hachCode على وجوه العناصر ، ثم التمسك بها في مجموعة...ولكن ظننت أنني يجب أن لا يقل استطلاع ستاكوفيرفلوو لمعرفة ما إذا كانت هناك طريقة أخرى ربما بعض ذكية طريقة أخرى API ؟
المحلول
أنا أتفق مع النهج الخاص بك إلى تجاوز hashCode()
و equals()
واستخدام شيء أن تنفذ Set
.
القيام بذلك أيضا يجعل من الواضح تماما أن أي المطورين أن عدم تكرار المميزة هو مطلوب.
سبب آخر - يمكنك الحصول على اختيار التنفيذ التي تلبي الاحتياجات الخاصة بك أفضل الآن:
وكنت لا تضطر إلى تغيير التعليمات البرمجية لتغيير التنفيذ في المستقبل.
نصائح أخرى
لقد وجدت هذا في موقع ويب
هنا نوعان من الطرق التي تسمح لك لإزالة التكرارات في ArrayList.removeDuplicate لا تحافظ على النظام حيث removeDuplicateWithOrder يحافظ على النظام مع بعض النفقات العامة الأداء.
على removeDuplicate الطريقة:
/** List order not maintained **/ public static void removeDuplicate(ArrayList arlList) { HashSet h = new HashSet(arlList); arlList.clear(); arlList.addAll(h); }
على removeDuplicateWithOrder الطريقة:
/** List order maintained **/ public static void removeDuplicateWithOrder(ArrayList arlList) { Set set = new HashSet(); List newList = new ArrayList(); for (Iterator iter = arlList.iterator(); iter.hasNext();) { Object element = iter.next(); if (set.add(element)) newList.add(element); } arlList.clear(); arlList.addAll(newList); }
وغلبة equals
وhashCode
وخلق مجموعة وفكرتي الأولى أيضا. انها ممارسة جيدة لديها بعض نسخة متجاوزة من هذه الأساليب على أي حال في التسلسل الهرمي ميراثك.
أنا <م> التفكير م> أنه إذا كنت تستخدم LinkedHashSet
عليك حتى الحفاظ على النظام من العناصر الفريدة ...
وأساسا، كنت ترغب في تنفيذ LinkedHashSet<T>
التي تدعم واجهة List<T>
عن الوصول العشوائي. وبالتالي، فإن هذا هو ما تحتاجه:
وpublic class LinkedHashSetList<T> extends LinkedHashSet<T> implements List<T> {
و// Implementations for List<T> methods here
...
و}
وتنفيذ الطرق List<T>
أن الوصول إلى والتلاعب LinkedHashSet<T>
الكامنة. هو خدعة لديك هذه الفئة تتصرف بشكل صحيح عندما يحاول أحدهم لإضافة مكررة عبر List<T>
إضافة أساليب (رمي استثناء أو إعادة إضافة هذا البند في مؤشر مختلفة ستكون خيارات: الذي يمكنك إما اختيار واحد أو جعل شكلي من قبل المستخدمين الطبقة).
استخدم ل distinctList
قائمة لتسجيل عنصر في المرة الأولى iterator
تتعثر في ذلك، إرجاع distinctList كقائمة إزالة جميع التكرارات
private List removeDups(List list) {
Set tempSet = new HashSet();
List distinctList = new ArrayList();
for(Iterator it = list.iterator(); it.hasNext();) {
Object next = it.next();
if(tempSet.add(next)) {
distinctList.add(next);
}
}
return distinctList;
}
وأود أن أكرر النقطة التي جيسون في التعليقات:
لماذا تضع نفسك في تلك المرحلة على الإطلاق؟
لماذا استخدام صفيف لبنية البيانات التي يجب أن لا عقد التكرارات في كل شيء؟
استخدم لSet
أو SortedSet
(عند وجود عناصر من النظام الطبيعي، وكذلك) في جميع الأوقات لعقد العناصر. إذا كنت بحاجة للحفاظ على ترتيب الإدراج، ثم يمكنك استخدام LinkedHashSet
كما تم الإشارة إلى.
والحاجة إلى ما بعد عملية بعض هياكل البيانات وغالبا ما يكون إشارة إلى أن يجب أن يكون اخترت واحدة مختلفة لتبدأ.
وبطبيعة الحال فإن آخر الأصلي يطرح هذا السؤال: "كيف يمكنك الحصول على ذلك مجموعة (التي قد تحتوي على إدخالات مكررة) في المقام الأول؟"
هل كنت في حاجة إلى مجموعة (مع التكرار) لأغراض أخرى، أو هل يمكن ببساطة استخدام مجموعة من البداية؟
وبدلا من ذلك، إذا كنت بحاجة إلى معرفة عدد الحوادث من كل قيمة، هل يمكن استخدام Map<CustomObject, Integer>
لتتبع التهم الموجهة إليه. أيضا، و تعريف مجموعات جوجل الطبقات Multimap قد تكون ذات فائدة.
وA Set
هو بالتأكيد أفضل رهان. الطريقة الوحيدة لإزالة الأشياء من مجموعة (بدون إنشاء واحد جديد) هي فارغة بها، ومن ثم إنهاء لكم مع الكثير من خالية الشيكات في وقت لاحق.
ويتحدث من مستوى البرمجة العام هل يمكن دائما ضعف تعداد مجموعات ثم المقارنة بين المصدر والهدف.
وإذا تعداد الداخلية الخاصة بك دائما يبدأ إدخال واحد بعد المصدر، انها فعالة إلى حد ما (الزائفة رمز لمتابعة)
foreach ( array as source )
{
// keep track where we are in the array
place++;
// loop the array starting at the entry AFTER the current one we are comparing to
for ( i=place+1; i < max(array); i++ )
{
if ( source === array[place] )
{
destroy(array[i]);
}
}
}
هل يمكن أن تضيف القول استراحة. بيان بعد تدمير ولكن بعد ذلك تكتشف سوى نسختين الأولى، ولكن إذا كان هذا هو كل ما سوف يكون من أي وقت مضى، فإنه سيكون الأمثل صغيرة لطيفة.