الفرز ArrayList من الكائنات باستخدام مخصص ترتيب الفرز

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

سؤال

أنا أبحث لتنفيذ نوعا ميزة بلدي دفتر العناوين التطبيق.

أريد أن فرز ArrayList<Contact> contactArray. Contact هي الطبقة التي تحتوي على أربعة مجالات:اسم, رقم المنزل ورقم الجوال والعنوان.أريد أن نوع على name.

كيف يمكنني كتابة فرز مخصص وظيفة أن تفعل هذا ؟

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

المحلول

هنا هو البرنامج التعليمي حول طلب الكائنات:

على الرغم من أنني سوف أعطي بعض الأمثلة ، أنصح قراءة ذلك على أي حال.


هناك العديد طريقة لفرز ArrayList.إذا كنت ترغب في تحديد الطبيعية (الافتراضي) يأمر, ثم تحتاج إلى السماح Contact تنفيذ Comparable.على افتراض أن كنت ترغب في فرز بشكل افتراضي على name, ثم هل (nullchecks أغفل عن البساطة):

public class Contact implements Comparable<Contact> {

    private String name;
    private String phone;
    private Address address;

    public int compareTo(Contact other) {
        return name.compareTo(other.name);
    }

    // Add/generate getters/setters and other boilerplate.
}

بحيث يمكنك فقط القيام به

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

Collections.sort(contacts);

إذا كنت ترغب في تحديد الخارجية السيطرة عليها طلب (التي يتجاوز الطبيعية الطلب), ثم تحتاج إلى إنشاء Comparator:

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Now sort by address instead of name (default).
Collections.sort(contacts, new Comparator<Contact>() {
    public int compare(Contact one, Contact other) {
        return one.getAddress().compareTo(other.getAddress());
    }
}); 

يمكنك حتى تحديد Comparators في Contact نفسه بحيث يمكن إعادة استخدامها بدلا من إعادة لهم في كل مرة:

public class Contact {

    private String name;
    private String phone;
    private Address address;

    // ...

    public static Comparator<Contact> COMPARE_BY_PHONE = new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.phone.compareTo(other.phone);
        }
    };

    public static Comparator<Contact> COMPARE_BY_ADDRESS = new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.address.compareTo(other.address);
        }
    };

}

والتي يمكن استخدامها على النحو التالي:

List<Contact> contacts = new ArrayList<Contact>();
// Fill it.

// Sort by address.
Collections.sort(contacts, Contact.COMPARE_BY_ADDRESS);

// Sort later by phone.
Collections.sort(contacts, Contact.COMPARE_BY_PHONE);

و كريم العليا ، يمكن أن تنظر في استخدام عام التخطيط الاستراتيجي المشترك javabean المقارنة:

public class BeanComparator implements Comparator<Object> {

    private String getter;

    public BeanComparator(String field) {
        this.getter = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
    }

    public int compare(Object o1, Object o2) {
        try {
            if (o1 != null && o2 != null) {
                o1 = o1.getClass().getMethod(getter, new Class[0]).invoke(o1, new Object[0]);
                o2 = o2.getClass().getMethod(getter, new Class[0]).invoke(o2, new Object[0]);
            }
        } catch (Exception e) {
            // If this exception occurs, then it is usually a fault of the developer.
            throw new RuntimeException("Cannot compare " + o1 + " with " + o2 + " on " + getter, e);
        }

        return (o1 == null) ? -1 : ((o2 == null) ? 1 : ((Comparable<Object>) o1).compareTo(o2));
    }

}

والتي يمكنك استخدامها على النحو التالي:

// Sort on "phone" field of the Contact bean.
Collections.sort(contacts, new BeanComparator("phone"));

(كما ترى في الكود ربما null الحقول مغطاة بالفعل لتجنب NPE خلال نوع)

نصائح أخرى

بالإضافة إلى ما تم بالفعل نشر يجب أن نعرف أنه منذ جافا 8 يمكننا تقصير مدونة والكتابة مثل:

Collection.sort(yourList, Comparator.comparing(YourClass::getFieldToSortOn));

أو قائمة منذ الآن sort طريقة

yourList.sort(Comparator.comparing(YourClass::getFieldToSortOn));

التفسير:

منذ جافا 8, واجهات وظيفية (واجهات مع ملخص واحد فقط الطريقة - يمكن أن يكون أكثر من التقصير أو أساليب ثابتة) يمكن تنفيذها بسهولة باستخدام:

منذ Comparator<T> واحد فقط مجردة طريقة int compare(T o1, T o2) هو واجهة وظيفية.

وذلك بدلا من (على سبيل المثال من @BalusC الجواب)

Collections.sort(contacts, new Comparator<Contact>() {
    public int compare(Contact one, Contact other) {
        return one.getAddress().compareTo(other.getAddress());
    }
}); 

ونحن يمكن أن تقلل من هذه التعليمة البرمجية:

Collections.sort(contacts, (Contact one, Contact other) -> {
     return one.getAddress().compareTo(other.getAddress());
});

يمكننا تبسيط هذا (أو أي) امدا من خلال تخطي

  • حجة أنواع (جافا سوف يستنتج منها على أساس طريقة التوقيع)
  • أو {return ... }

وذلك بدلا من

(Contact one, Contact other) -> {
     return one.getAddress().compareTo(other.getAddress();
}

يمكن أن نكتب

(one, other) -> one.getAddress().compareTo(other.getAddress())

أيضا الآن Comparator وقد أساليب ثابتة مثل comparing(FunctionToComparableValue) أو comparing(FunctionToValue, ValueComparator) التي يمكن أن تستخدم بسهولة لخلق الكائنات المرجعية التي ينبغي مقارنة لبعض قيم معينة من الكائنات.

وبعبارة أخرى يمكننا إعادة كتابة رمز أعلاه كما

Collections.sort(contacts, Comparator.comparing(Contact::getAddress)); 
//assuming that Address implements Comparable (provides default order).

هذه الصفحة يقول لك كل ما تحتاج إلى معرفته حول فرز مجموعات مثل ArrayList.

في الأساس تحتاج إلى

  • جعل الخاص بك Contact الطبقة تنفيذ Comparable واجهة من قبل
    • إنشاء طريقة public int compareTo(Contact anotherContact) في غضون ذلك.
  • بمجرد القيام بذلك, يمكنك فقط الاتصال Collections.sort(myContactList);,
    • حيث myContactList هو ArrayList<Contact> (أو أي مجموعة أخرى من Contact).

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

على سبيل المثال:

public class Contact implements Comparable<Contact> {

    ....

    //return -1 for less than, 0 for equals, and 1 for more than
    public compareTo(Contact anotherContact) {
        int result = 0;
        result = getName().compareTo(anotherContact.getName());
        if (result != 0)
        {
            return result;
        }
        result = getNunmber().compareTo(anotherContact.getNumber());
        if (result != 0)
        {
            return result;
        }
        ...
    }
}

وBalusC وbguiz قدموا بالفعل إجابات كاملة للغاية حول كيفية استخدام جافا الذي بني في مقارنات.

وأريد فقط أن أضيف أن جوجل-مجموعات لها <لأ href = "http://google-collections.googlecode.com/svn/trunk/javadoc/index.html؟com/google/common/collect/Ordering أتش تي أم أل "يختلط =" نوفولو noreferrer "عنوان =" جافادوك com.google.common.collect.Ordering "> طلب الدرجة التي هي أكثر" قوية "من مقارنات معيارية. قد يكون من المفيد التدقيق بها. يمكنك أن تفعل أشياء باردة مثل يضاعف أوامر شراء، وعكس لهم، وطلب اعتمادا على نتيجة وظيفة للالأشياء الخاصة بك ...

<وأ href = "http://codemunchies.com/2009/11/functional-java-filtering-and-ordering-with-google-collections-part-3/" يختلط = "نوفولو noreferrer" عنوان = " وظيفية جافا، تصفية والترتيب مع مجموعات جوجل (الجزء 3) "> هنا هو بلوق وظيفة أن يذكر بعض من فوائدها.

تحتاج إلى جعل الاتصال الخاصة بك الطبقات تنفيذ للمقارنة, ثم تنفيذ compareTo(Contact) الأسلوب.بهذه الطريقة, مجموعات.النوع سوف تكون قادرة على فرز لهم لك.في الصفحة المرتبطة compareTo 'بإرجاع عدد صحيح السلبي صفر أو عدد صحيح موجب مثل هذا الكائن هو أقل من يساوي أو أكبر من الكائن المحدد.'

على سبيل المثال, إذا أردت الفرز حسب اسم (A إلى Z) ، صفك سوف تبدو مثل هذا:

public class Contact implements Comparable<Contact> {

    private String name;

    // all the other attributes and methods

    public compareTo(Contact other) {
        return this.name.compareTo(other.name);
    }
}

lambdaj الذي يمكن فرز مجموعة من جهات الاتصال الخاصة بك (على سبيل المثال بهم اسم) كما يلي

sort(contacts, on(Contact.class).getName());

وأو عناوينهم:

sort(contacts, on(Contacts.class).getAddress());

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

ووCollections.sort هو تطبيق نوع جيد. إذا لم يكن لديك ومقارنتها تنفيذها لالاتصال، سوف تحتاج إلى تمرير في <لأ href = "http://java.sun.com/javase/6/docs/api/java/util/Collections.html# نوع (java.util.List،٪ 20java.util.Comparator) "يختلط =" نوفولو noreferrer "> تنفيذ المقارنة

ومن ملاحظة:

<اقتباس فقرة>   

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

وهذا النوع الدمج هو على الارجح أفضل من معظم خوارزمية البحث يمكنك القيام به.

وأنا فعلت هذا قبل على النحو التالي. عدد واسم نوعان arraylist. لا بد لي من فرز اسم. إذا أي تغيير يحدث على سبيل المثال arralist أجل ثم arraylist العدد أيضا تغيير نظامها.

public void sortval(){

        String tempname="",tempnum="";

         if (name.size()>1) // check if the number of orders is larger than 1
            {
                for (int x=0; x<name.size(); x++) // bubble sort outer loop
                {
                    for (int i=0; i < name.size()-x-1; i++) {
                        if (name.get(i).compareTo(name.get(i+1)) > 0)
                        {

                            tempname = name.get(i);

                            tempnum=number.get(i);


                           name.set(i,name.get(i+1) );
                           name.set(i+1, tempname);

                            number.set(i,number.get(i+1) );
                            number.set(i+1, tempnum);


                        }
                    }
                }
            }



}

استخدم هذا الأسلوب:

private ArrayList<myClass> sortList(ArrayList<myClass> list) {
    if (list != null && list.size() > 1) {
        Collections.sort(list, new Comparator<myClass>() {
            public int compare(myClass o1, myClass o2) {
                if (o1.getsortnumber() == o2.getsortnumber()) return 0;
                return o1.getsortnumber() < o2.getsortnumber() ? 1 : -1;
            }
        });
    }
    return list;
}

و`

ووالاستخدام: mySortedlist = sortList(myList); لا حاجة لتنفيذ المقارنة في صفك. إذا كنت تريد معكوس 1 أجل تبادل و-1

ويجب عليك استخدام وظيفة Arrays.sort. يجب أن الطبقات التي تحتوي على تنفيذ المقارن.

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