ما هي أفضل طريقة لإزالة التكرارات في صفيف في جافا ؟

StackOverflow https://stackoverflow.com/questions/357421

  •  21-08-2019
  •  | 
  •  

سؤال

لدي مجموعة من الكائنات التي تحتاج إلى إزالة التكرارات/تصفيتها.كنت ذاهبا لمجرد تجاوز يساوي & hachCode على وجوه العناصر ، ثم التمسك بها في مجموعة...ولكن ظننت أنني يجب أن لا يقل استطلاع ستاكوفيرفلوو لمعرفة ما إذا كانت هناك طريقة أخرى ربما بعض ذكية طريقة أخرى API ؟

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

المحلول

أنا أتفق مع النهج الخاص بك إلى تجاوز hashCode() و equals() واستخدام شيء أن تنفذ Set.

القيام بذلك أيضا يجعل من الواضح تماما أن أي المطورين أن عدم تكرار المميزة هو مطلوب.

سبب آخر - يمكنك الحصول على اختيار التنفيذ التي تلبي الاحتياجات الخاصة بك أفضل الآن:

وكنت لا تضطر إلى تغيير التعليمات البرمجية لتغيير التنفيذ في المستقبل.

نصائح أخرى

لقد وجدت هذا في موقع ويب

هنا نوعان من الطرق التي تسمح لك لإزالة التكرارات في ArrayList.removeDuplicate لا تحافظ على النظام حيث removeDuplicateWithOrder يحافظ على النظام مع بعض النفقات العامة الأداء.

  1. على removeDuplicate الطريقة:

    /** List order not maintained **/
    public static void removeDuplicate(ArrayList arlList)
    {
     HashSet h = new HashSet(arlList);
     arlList.clear();
     arlList.addAll(h);
    }
    
  2. على 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]);
        }
    }
}

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

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