कस्टम छँटाई क्रम का उपयोग करके वस्तुओं के एक ArrayList को क्रमबद्ध करना


119

मैं अपने पता पुस्तिका आवेदन के लिए एक तरह की सुविधा को लागू करने के लिए देख रहा हूं।

मैं एक छांटना चाहता हूं ArrayList<Contact> contactArrayContactएक वर्ग है जिसमें चार क्षेत्र शामिल हैं: नाम, घर का नंबर, मोबाइल नंबर और पता। मैं छांटना चाहता हूं name

मैं ऐसा करने के लिए एक कस्टम प्रकार फ़ंक्शन कैसे लिख सकता हूं?

जवाबों:


270

यहां ऑब्जेक्ट्स ऑर्डर करने के बारे में एक ट्यूटोरियल है:

हालाँकि मैं कुछ उदाहरण दूंगा, फिर भी मैं इसे पढ़ने की सलाह दूंगा।


सॉर्ट करने के लिए विभिन्न तरीके हैं 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());
    }
}); 

आप स्वयं Comparatorमें s को भी परिभाषित 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);

और ऊपर से क्रीम लगाने के लिए, आप जेनेरिक जेवबीन तुलनित्र का उपयोग करने पर विचार कर सकते हैं :

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"));

(जैसा कि आप कोड में देखते हैं, संभवतया अशक्त फ़ील्ड NPE के दौरान सॉर्ट से बचने के लिए पहले से ही कवर किए गए हैं)


2
मैं कई तुलनाकर्ताओं को पूर्व-परिभाषित करने की संभावना जोड़ूंगा, और फिर उन्हें नाम से उपयोग करूंगा ...
Stobor

2
वास्तव में, मैंने अभी किया। खुद को समझाने की कोशिश करने से ज्यादा आसान है।
Stobor

@ बालसैक: कोई जांच नहीं। मैं इस विचार का श्रेय नहीं ले सकता, मुझे यह String.CASE_INSENSITIVE_ORDERदोस्तों और दोस्तों से मिला लेकिन मुझे यह पसंद है। परिणामी कोड को पढ़ना आसान बनाता है।
स्टोबोर

1
उन तुलनित्र परिभाषाएँ भी शायद होनी चाहिए staticऔर शायद finalभी ... या ऐसा ही कुछ ..
Stobor

Heheh ... BeanComparator एक छड़ी पर बहुत बढ़िया की तरह है! :-) (मुझे nulls की सटीक तर्क तुलना याद नहीं है, लेकिन क्या यह (o1 == null && o2 == null) ? 0 :उस वापसी लाइन की शुरुआत में चाहता है ?)
Stobor

28

पहले से ही जो पोस्ट किया गया था उसके अलावा आपको पता होना चाहिए कि जावा 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).

8

यह पृष्ठ बताता है कि आपको 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;
        }
        ...
    }
}

5

BalusC और bguiz ने पहले ही बहुत पूर्ण उत्तर दे दिए हैं कि जावा के अंतर्निहित कंप्रेशर्स का उपयोग कैसे करें।

मैं बस यह जोड़ना चाहता हूं कि Google-संग्रहों में एक आदेश वर्ग है जो मानक तुलनाकर्ताओं की तुलना में अधिक "शक्तिशाली" है। यह जाँच के लायक हो सकता है। आप कंपाउंडिंग ऑर्डर जैसे शांत चीजें कर सकते हैं, उन्हें उलट सकते हैं, अपनी वस्तुओं के लिए एक फ़ंक्शन के परिणाम के आधार पर ऑर्डर कर सकते हैं ...

यहाँ एक ब्लॉग पोस्ट है जिसमें इसके कुछ लाभों का उल्लेख है।


ध्यान दें कि Google-संग्रह अब अमरूद (Google की आम जावा लाइब्रेरी) का एक हिस्सा है, इसलिए यदि आप ऑर्डरिंग क्लास का उपयोग करना चाहते हैं, तो आप अमरूद (या अमरूद के संग्रह मॉड्यूल) पर निर्भर रहना चाह सकते हैं।
एटिएन नेवू

4

आपको अपनी संपर्क कक्षाओं को तुलनात्मक लागू करने की आवश्यकता है , और फिर compareTo(Contact)विधि को लागू करें । इस तरह, आप के लिए संग्रह। Sort उन्हें सॉर्ट करने में सक्षम होंगे। मैं जिस पेज से जुड़ा हुआ हूं, उसकी तुलना में 'एक नकारात्मक पूर्णांक, शून्य या एक सकारात्मक पूर्णांक देता है क्योंकि यह ऑब्जेक्ट निर्दिष्ट ऑब्जेक्ट से कम, बराबर या उससे अधिक है।'

उदाहरण के लिए, यदि आप नाम (ए से जेड) के अनुसार क्रमबद्ध करना चाहते हैं, तो आपकी कक्षा इस तरह दिखाई देगी:

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);
    }
}

मेरे साथ अच्छी तरह से काम किया, धन्यवाद! मैं भी मामले की अनदेखी करने के लिए ComparToIgnoreCase का इस्तेमाल किया।
रानी खीर

3

Lambdaj का उपयोग करके आप अपने संपर्कों का एक संग्रह (उदाहरण के लिए उनके नाम से) सॉर्ट कर सकते हैं जैसा कि यह निम्नानुसार है

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

या उनके पते से:

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

और इसी तरह। सामान्य तौर पर, यह आपके संग्रह को कई तरीकों से एक्सेस करने और हेरफेर करने के लिए एक डीएसएल प्रदान करता है, जैसे कुछ शर्तों के आधार पर अपने संपर्कों को फ़िल्टर करना या समूहित करना, उनके कुछ संपत्ति मूल्यों को एकत्र करना, आदि।


0

इस संग्रह। एक अच्छा कार्यान्वयन है। यदि आपके पास संपर्क के लिए तुलनीय लागू नहीं है, तो आपको एक तुलनित्र कार्यान्वयन में पास करना होगा

टिप्पणी का:

सॉर्टिंग एल्गोरिथ्म एक संशोधित मर्जर्ट है (जिसमें मर्ज को छोड़ दिया जाता है यदि कम सबलिस्ट में उच्चतम तत्व उच्च सबलिस्ट में सबसे कम तत्व से कम है)। यह एल्गोरिथ्म गारंटीकृत n लॉग (n) प्रदर्शन प्रदान करता है। निर्दिष्ट सूची को संशोधित किया जाना चाहिए, लेकिन इसे बदलने योग्य नहीं होना चाहिए। यह कार्यान्वयन निर्दिष्ट सूची को एक सरणी में रखता है, सरणी को सॉर्ट करता है, और सरणी में संबंधित स्थिति से प्रत्येक तत्व को रीसेट करने वाली सूची पर पुनरावृत्त करता है। यह n2 लॉग (n) प्रदर्शन से बचा जाता है, जिसके परिणामस्वरूप लिंक की गई सूची को क्रमबद्ध करने का प्रयास किया जाएगा।

मर्ज सॉर्ट संभवतः आपके द्वारा किए जा सकने वाले अधिकांश खोज एल्गोरिदम से बेहतर है।


0

मैंने इसे निम्नलिखित तरीके से किया। संख्या और नाम दो सरणी सूची हैं। मुझे नाम क्रमबद्ध करना है। यदि कोई नाम बदलकर अरैलिस्ट ऑर्डर हो जाता है तो नंबर सरणीलिस्ट भी अपना ऑर्डर बदल देती है।

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);


                        }
                    }
                }
            }



}

आप इसे लिखने में अधिक समय ले रहे हैं, कम इष्टतम सॉर्ट प्रदर्शन प्राप्त करते हैं, अधिक बग (और उम्मीद से अधिक परीक्षण) लिखते हैं, और कोड अन्य लोगों को स्थानांतरित करने के लिए कठिन होगा। तो यह सही नहीं है। यह काम कर सकता है, लेकिन यह इसे सही नहीं करता है।
एरिक

0

इस विधि का उपयोग करें:

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


0

ठीक है, मुझे पता है कि यह एक लंबे समय से पहले उत्तर दिया गया था ... लेकिन, यहाँ कुछ नई जानकारी है:

कहो कि संपर्क वर्ग में पहले से ही तुलनात्मक कार्यान्वयन के माध्यम से एक परिभाषित प्राकृतिक आदेश है, लेकिन आप उस आदेश को ओवरराइड करना चाहते हैं, नाम से कहें। यहाँ यह करने का आधुनिक तरीका है:

List<Contact> contacts = ...;

contacts.sort(Comparator.comparing(Contact::getName).reversed().thenComparing(Comparator.naturalOrder());

इस तरह यह पहले (रिवर्स ऑर्डर में) नाम से सॉर्ट करेगा, और फिर नाम टकराव के लिए यह संपर्क वर्ग द्वारा लागू किए गए 'प्राकृतिक' ऑर्डर पर वापस आ जाएगा।


-1

आप Arrays.sort फ़ंक्शन का उपयोग करते हैं। युक्त वर्गों को तुलनीय लागू करना चाहिए।


इसलिए मैंने अर्र्स कहा।
23

समस्या यह है कि ओपी सरणी का उपयोग कर रहा है, सरणी का नहीं।
साहीमो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.