कुछ संपत्ति द्वारा वस्तुओं की सूची को कैसे छाँटा जाए


145

मेरे पास साधारण वर्ग है

public class ActiveAlarm {
    public long timeStarted;
    public long timeEnded;
    private String name = "";
    private String description = "";
    private String event;
    private boolean live = false;
}

और List<ActiveAlarm>चोर। कैसे timeStarted, तब तक आरोही क्रम में क्रमबद्ध करें timeEnded? क्या कोई मदद कर सकता है? मैं सामान्य एल्गोरिथ्म और अधिभार ऑपरेटर <के साथ सी ++ में जानता हूं, लेकिन मैं जावा के लिए नया हूं।


इस पोस्ट में @Yishai द्वारा जवाब कस्टम छँटाई और समूहबद्ध छँटाई (कई तर्क) के लिए Enum का सुरुचिपूर्ण उपयोग तुलनित्र जंजीरों का उपयोग दर्शाता है।
गनमेल सेप

जवाबों:


140

या तो अलग वर्ग में ActiveAlarmलागू करें Comparable<ActiveAlarm>या लागू करें Comparator<ActiveAlarm>। फिर कॉल करो:

Collections.sort(list);

या

Collections.sort(list, comparator);

सामान्य तौर पर, इसे लागू करने के एक अच्छा विचार है Comparable<T>अगर वहाँ एक भी "प्राकृतिक" सॉर्ट क्रम है ... अन्यथा (यदि आप ऐसा एक विशेष क्रम में सॉर्ट करने के लिए करना चाहते हैं, लेकिन समान रूप से आसानी से एक अलग से एक चाहते हो सकता है) इसे लागू करने से बेहतर है Comparator<T>। यह विशेष स्थिति किसी भी तरह से जा सकती है, ईमानदार होने के लिए ... लेकिन मैं शायद अधिक लचीले Comparator<T>विकल्प के साथ रहना चाहूंगा ।

संपादित करें: नमूना कार्यान्वयन:

public class AlarmByTimesComparer implements Comparator<ActiveAlarm> {
  @Override
  public int compare(ActiveAlarm x, ActiveAlarm y) {
    // TODO: Handle null x or y values
    int startComparison = compare(x.timeStarted, y.timeStarted);
    return startComparison != 0 ? startComparison
                                : compare(x.timeEnded, y.timeEnded);
  }

  // I don't know why this isn't in Long...
  private static int compare(long a, long b) {
    return a < b ? -1
         : a > b ? 1
         : 0;
  }
}

1
यह तुलना () फ़ंक्शन लंबे समय तक संभव नहीं है क्योंकि कार्यान्वयन और भी अधिक तुच्छ है: वापसी - ए - बी;
पेपरक्रैन

5
@papercrane: नहीं, कि अतिप्रवाह कारणों के लिए विफल रहता है। विचार करें a = Long.MIN_VALUE, b = 1
जॉन स्कीट

3
एपीआई 19 (किटकैट) के रूप में लंबे समय तक एक.compare
मार्टिन मार्कोसिनी

123

का उपयोग करते हुए Comparator

उदाहरण के लिए:

class Score {

    private String name;
    private List<Integer> scores;
    // +accessor methods
}

    Collections.sort(scores, new Comparator<Score>() {

        public int compare(Score o1, Score o2) {
            // compare two instance of `Score` and return `int` as result.
            return o2.getScores().get(0).compareTo(o1.getScores().get(0));
        }
    });

जावा 8 के बाद, आप बस तुलनात्मक उदाहरण का प्रतिनिधित्व करने के लिए लैम्ब्डा अभिव्यक्ति का उपयोग कर सकते हैं।

Collections.sort(scores, (s1, s2) -> { /* compute and return int */ });

1
क्या करता compareTo()है? यह कहां से आता है? मुझे इसे कहां परिभाषित करना है?
असिकिर

1
@ अस्सकीर getScores()वह गटर है scoresजिसके लिए ए List<Integer>। जब आप getScores().get(0)कोई Integerवस्तु प्राप्त करते हैं Integerपहले से ही compareTo(anotherInteger)लागू विधि है, आपको इसे परिभाषित नहीं करना है।
10

क्या है (0)?
अली खाकी

1
धन्यवाद एक आकर्षण की तरह काम करता है (मैं .get (0) भाग के बिना इसका उपयोग करता हूं)। मैं कैसे आदेश को उलट सकता है?

53

जावा 8 और उससे अधिक उत्तर (लैम्ब्डा एक्सप्रेशंस का उपयोग करके)

जावा 8 में, इसे और भी आसान बनाने के लिए लैम्ब्डा एक्सप्रेशन पेश किए गए थे! इसकी तुलना मचान के साथ एक तुलनित्र () ऑब्जेक्ट बनाने के बजाय, आप इसे निम्नानुसार सरल कर सकते हैं: (उदाहरण के लिए अपनी वस्तु का उपयोग करना)

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted);

या इससे भी कम:

Collections.sort(list, Comparator.comparingInt(ActiveAlarm ::getterMethod));

यह एक कथन निम्नलिखित के बराबर है:

Collections.sort(list, new Comparator<ActiveAlarm>() {
    @Override
    public int compare(ActiveAlarm a1, ActiveAlarm a2) {
        return a1.timeStarted - a2.timeStarted;
    }
});

लैम्ब्डा के भावों के बारे में सोचें क्योंकि आपको केवल कोड के संबंधित भागों में डालने की आवश्यकता होती है: विधि हस्ताक्षर और क्या वापस मिलता है।

आपके प्रश्न का एक और हिस्सा था कि कैसे कई क्षेत्रों के खिलाफ तुलना की जाए। ऐसा करने के लिए कि लैम्ब्डा अभिव्यक्ति के साथ, आप .thenComparing()दो तुलनाओं को एक में प्रभावी ढंग से संयोजित करने के लिए फ़ंक्शन का उपयोग कर सकते हैं :

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.timeStarted-a2.timeStarted             
       .thenComparing ((ActiveAlarm a1, ActiveAlarm a2) -> a1.timeEnded-a2.timeEnded)
);

उपरोक्त कोड सूची को पहले timeStartedऔर फिर timeEndedउन रिकॉर्ड्स के लिए क्रमबद्ध करेगा (जिनके पास समान है timeStarted)।

एक अंतिम नोट: 'लॉन्ग' या 'इंट' प्राइमिटिव्स की तुलना करना आसान है, आप बस एक को दूसरे से घटा सकते हैं। यदि आप वस्तुओं ('लंबी' या 'स्ट्रिंग') की तुलना कर रहे हैं, तो मेरा सुझाव है कि आप उनकी अंतर्निहित तुलना का उपयोग करें। उदाहरण:

Collections.sort(list, (ActiveAlarm a1, ActiveAlarm a2) -> a1.name.compareTo(a2.name) );

संपादित करें: मुझे .thenComparing()काम करने के लिए इशारा करने के लिए लुकास ईडर का धन्यवाद ।


4
आप नए जावा 8 एपीआई की सराहना कर सकते हैं Comparator.comparing().thenComparing()...
लुकास ईडर

1
वापसी अंतर के साथ बाहर देखो। अतिप्रवाह के मामले में, आप गलत परिणाम प्राप्त कर सकते हैं।
krzychu

2
यह IMHO आसान छँटाई विधि है, फिर से मान लें कि आपके पास एक स्पष्ट प्राकृतिक क्रम नहीं है। आपको Collectionsअब कॉल करने की भी आवश्यकता नहीं है, आप सीधे सूची पर कॉल कर सकते हैं। उदाहरण के लिए:myList.sort(Comparator.comparing(Address::getZipCode).thenComparing(Compartor.comparing(Address::getStreetName));
CeePlusPlus

20

हम सूची को दो तरीकों में से एक में सॉर्ट कर सकते हैं:

1. तुलनित्र का उपयोग करना : जब कई स्थानों पर सॉर्ट लॉजिक का उपयोग करना आवश्यक हो, यदि आप एक ही स्थान पर सॉर्टिंग लॉजिक का उपयोग करना चाहते हैं, तो आप निम्न के रूप में एक अनाम इनर क्लास लिख सकते हैं, या फिर इक्वेटर को निकालें और इसे कई स्थानों पर उपयोग करें

  Collections.sort(arrayList, new Comparator<ActiveAlarm>() {
        public int compare(ActiveAlarm o1, ActiveAlarm o2) {
            //Sorts by 'TimeStarted' property
            return o1.getTimeStarted()<o2.getTimeStarted()?-1:o1.getTimeStarted()>o2.getTimeStarted()?1:doSecodaryOrderSort(o1,o2);
        }

        //If 'TimeStarted' property is equal sorts by 'TimeEnded' property
        public int doSecodaryOrderSort(ActiveAlarm o1,ActiveAlarm o2) {
            return o1.getTimeEnded()<o2.getTimeEnded()?-1:o1.getTimeEnded()>o2.getTimeEnded()?1:0;
        }
    });

हम गुणों के लिए अशक्त जांच कर सकते हैं, अगर हम 'लॉन्ग' की जगह 'लॉन्ग' का इस्तेमाल कर सकते थे।

2. तुलनीय (प्राकृतिक आदेश) का उपयोग करना : यदि सॉर्ट एल्गोरिथ्म हमेशा एक संपत्ति से चिपके रहते हैं: एक वर्ग लिखें जो 'तुलना' लागू करता है और 'तुलना' विधि को नीचे बताए अनुसार ओवरराइड करता है

class ActiveAlarm implements Comparable<ActiveAlarm>{

public long timeStarted;
public long timeEnded;
private String name = "";
private String description = "";
private String event;
private boolean live = false;

public ActiveAlarm(long timeStarted,long timeEnded) {
    this.timeStarted=timeStarted;
    this.timeEnded=timeEnded;
}

public long getTimeStarted() {
    return timeStarted;
}

public long getTimeEnded() {
    return timeEnded;
}

public int compareTo(ActiveAlarm o) {
    return timeStarted<o.getTimeStarted()?-1:timeStarted>o.getTimeStarted()?1:doSecodaryOrderSort(o);
}

public int doSecodaryOrderSort(ActiveAlarm o) {
    return timeEnded<o.getTimeEnded()?-1:timeEnded>o.getTimeEnded()?1:0;
}

}

प्राकृतिक क्रम के आधार पर सॉर्ट करने के लिए सॉर्ट विधि

Collections.sort(list);

7

Java8 + में इसे एकल पंक्ति में इस प्रकार लिखा जा सकता है:

collectionObjec.sort(comparator_lamda) या comparator.comparing(CollectionType::getterOfProperty)

कोड:

ListOfActiveAlarmObj.sort((a,b->a.getTimeStarted().compareTo(b.getTimeStarted())))
 

या

ListOfActiveAlarmObj.sort(Comparator.comparing(ActiveAlarm::getTimeStarted))

5
public class ActiveAlarm implements Comparable<ActiveAlarm> {
    public long timeStarted;
    public long timeEnded;
    private String name = "";
    private String description = "";
    private String event;
    private boolean live = false;

    public int compareTo(ActiveAlarm a) {
        if ( this.timeStarted > a.timeStarted )
            return 1;
        else if ( this.timeStarted < a.timeStarted )
            return -1;
        else {
             if ( this.timeEnded > a.timeEnded )
                 return 1;
             else
                 return -1;
        }
 }

जो आपको एक मोटा विचार देना चाहिए। एक बार जब आप ऐसा कर लेते हैं, तो आप Collections.sort()सूची पर कॉल कर सकते हैं ।


4

Java8 के बाद से यह Comparatorऔर के संयोजन का उपयोग करके भी साफ किया जा सकता हैLambda expressions

उदाहरण के लिए:

class Student{

    private String name;
    private List<Score> scores;

    // +accessor methods
}

class Score {

    private int grade;
    // +accessor methods
}

    Collections.sort(student.getScores(), Comparator.comparing(Score::getGrade);



1

जावा में आपको स्थैतिक Collections.sortविधि का उपयोग करने की आवश्यकता है । कंपनीरोल ऑब्जेक्ट्स की सूची के लिए एक उदाहरण यहां दिया गया है, पहले शुरू और फिर अंत तक क्रमबद्ध। आप आसानी से अपनी खुद की वस्तु के लिए अनुकूलित कर सकते हैं।

private static void order(List<TextComponent> roles) {

    Collections.sort(roles, new Comparator() {
        @Override
        public int compare(Object o1, Object o2) {
            int x1 = ((CompanyRole) o1).getBegin();
            int x2 = ((CompanyRole) o2).getBegin();

            if (x1 != x2) {
                return x1 - x2;
            } else {
                int y1 = ((CompanyRole) o1).getEnd();
                int y2 = ((CompanyRole) o2).getEnd();
                return y2 - y1;
            }
        }
    });
}

0

आप Collections.sort () को कॉल कर सकते हैं और एक तुलनित्र में पास कर सकते हैं जिसे आपको ऑब्जेक्ट के विभिन्न गुणों की तुलना करने के लिए लिखना होगा।


0

जैसा कि आप उल्लेख कर सकते हैं:

  • अपनी वस्तु को कार्यान्वित करना Comparable
  • या पास ComparatorहोCollections.sort

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

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