ArrayList में वस्तुओं को तिथि के अनुसार क्रमबद्ध करें?


149

मेरे द्वारा पाया गया प्रत्येक उदाहरण वर्णानुक्रम में ऐसा करने के बारे में है, जबकि मुझे अपने तत्वों को तिथि के अनुसार क्रमबद्ध करने की आवश्यकता है।

मेरे ArrayList में ऐसी वस्तुएँ हैं जिन पर डेटामेम्बर्स में से एक डेटाइम ऑब्जेक्ट है। दिनांक समय पर मैं फ़ंक्शन को कॉल कर सकता हूं:

lt() // less-than
lteq() // less-than-or-equal-to

इसलिए तुलना करने के लिए मैं कुछ ऐसा कर सकता था:

if(myList.get(i).lt(myList.get(j))){
    // ...
}

अगर मुझे ब्लॉक करना है तो मुझे क्या करना चाहिए?


3
मैंने समाधान पोस्ट किया है, लेकिन यदि आप ऑर्डर करने के लिए एक अंतर्दृष्टि प्राप्त करना चाहते हैं तो आपको एल्गोरिदम (बबलर्ट्स, मर्जसॉर्ट, क्विकसॉर्ट, आदि) के बारे में पढ़ना चाहिए।
हेलियोस

धन्यवाद, मैं उन पर एक नज़र

इस धागे में कई उपयोगी जावा 1.8 समाधान पाए जा सकते हैं: stackoverflow.com/questions/36361156/…
lradacher

जवाबों:


417

आप अपनी वस्तु को तुलनीय बना सकते हैं:

public static class MyObject implements Comparable<MyObject> {

  private Date dateTime;

  public Date getDateTime() {
    return dateTime;
  }

  public void setDateTime(Date datetime) {
    this.dateTime = datetime;
  }

  @Override
  public int compareTo(MyObject o) {
    return getDateTime().compareTo(o.getDateTime());
  }
}

और फिर आप इसे कॉल करके सॉर्ट करें:

Collections.sort(myList);

हालाँकि कभी-कभी आप अपने मॉडल को बदलना नहीं चाहते हैं, जैसे कि जब आप कई अलग-अलग गुणों को क्रमबद्ध करना चाहते हैं। उस स्थिति में, आप मक्खी पर तुलनित्र बना सकते हैं:

Collections.sort(myList, new Comparator<MyObject>() {
  public int compare(MyObject o1, MyObject o2) {
      return o1.getDateTime().compareTo(o2.getDateTime());
  }
});

हालाँकि, उपरोक्त कार्य तभी होता है जब आप निश्चित हों कि तुलना के समय डेटटाइम शून्य नहीं है। यह NullPointerException से बचने के लिए null को संभालने के लिए समझदारी है:

public static class MyObject implements Comparable<MyObject> {

  private Date dateTime;

  public Date getDateTime() {
    return dateTime;
  }

  public void setDateTime(Date datetime) {
    this.dateTime = datetime;
  }

  @Override
  public int compareTo(MyObject o) {
    if (getDateTime() == null || o.getDateTime() == null)
      return 0;
    return getDateTime().compareTo(o.getDateTime());
  }
}

या दूसरे उदाहरण में:

Collections.sort(myList, new Comparator<MyObject>() {
  public int compare(MyObject o1, MyObject o2) {
      if (o1.getDateTime() == null || o2.getDateTime() == null)
        return 0;
      return o1.getDateTime().compareTo(o2.getDateTime());
  }
});

1
अच्छा उत्तर। आपको शून्य जाँच के बिना संस्करणों को शामिल करने की आवश्यकता क्यों है? फायदा क्या है? यदि सही तरीका दूसरा है तो आप केवल इसे शामिल कर सकते हैं और महत्वपूर्ण जानकारी को अधिक आकर्षक बना सकते हैं।
14

17
दो कारण - सादगी और असफलता-उपवास। आप चाहते हैं कि कोड यथासंभव सरल हो, और यदि आप निश्चित हैं कि आपकी संपत्ति शून्य नहीं होनी चाहिए, तो आप चाहते हैं कि आपका कोड जितनी जल्दी हो सके विफल हो जाए, अगर आप अवैध डेटा के बजाय, अवैध डेटा को पारित करने और जगह से आगे तोड़ने के बजाय। जहां अमान्य डेटा पेश किया गया था।
डोमची 10/1012

3
यदि o1 या o2 शून्य है, तो 0 लौटाएं; // यह लाइन बग का कारण बन सकती है क्योंकि वापसी 0 का अर्थ है कि वे समान हैं।
तनिहेज़ेंग

@tanyehzheng, यह सही है, यह भ्रामक है, लेकिन ध्यान दें कि .compareTo () के बीच अंतर है जो छँटाई और असमानता () के लिए उपयोग किया जाता है। यह वास्तव में इस बात पर निर्भर करता है कि आप अपने नल को किस तरह से संभालना चाहते हैं।
डोमची

1
आपको प्रत्येक तिथि की अशक्तता के लिए अलग से जांच करनी चाहिए और इच्छानुसार क्रमबद्ध (शुरुआत के अंत या अंत में या तो अशक्त) करना चाहिए। यही है, अगर एक तारीख शून्य है और एक अशक्त नहीं है, तो 1 या -1 लौटाएं। ऐसा किए बिना, नल को छांटा नहीं जाता है और जहां भी वे छंटनी से पहले सूची में होते हैं, वहां बने रहते हैं।
droozen

64

जावा 8 के बाद से सूची इंटरफ़ेस सॉर्ट विधि प्रदान करता है । लैंबडा अभिव्यक्ति के साथ संयुक्त सबसे आसान समाधान होगा

// sort DateTime typed list
list.sort((d1,d2) -> d1.compareTo(d2));
// or an object which has an DateTime attribute
list.sort((o1,o2) -> o1.getDateTime().compareTo(o2.getDateTime()));
// or like mentioned by Tunaki
list.sort(Comparator.comparing(o -> o.getDateTime()));

उल्टे छँटनी

Java 8 रिवर्स सॉर्टिंग के लिए कुछ आसान तरीकों के साथ भी आता है।

//requested by lily
list.sort(Comparator.comparing(o -> o.getDateTime()).reversed());

8
इससे भी बेहतर होगाlist.sort(Comparator.comparing(o -> o.getDateTime()));
तुनाकी

21
इस बारे में कैसे:list.sort(Comparator.comparing(MyObject::getDateTime)
व्हाइटब्रो

@Tunaki रिवर्स सॉर्टिंग कैसे करें?
लिली

18

आप Collections.sort पद्धति का उपयोग कर सकते हैं। यह एक स्थिर विधि है। आप इसे सूची और एक तुलनित्र पास करते हैं। यह सूची में एक संशोधित मर्जर्ट एल्गोरिथ्म का उपयोग करता है। इसलिए आपको जोड़ी की तुलना करने के लिए एक तुलनित्र होना चाहिए।

Collections.sort(myList, new Comparator<MyObject> {
   public int compare(MyObject o1, MyObject o2) {
      DateTime a = o1.getDateTime();
      DateTime b = o2.getDateTime();
      if (a.lt(b)) 
        return -1;
      else if (a.lteq(b)) // it's equals
         return 0;
      else
         return 1;
   }
});

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


1
और जब यह किया जाता है या ऐसा कुछ होता है तो क्या यह मायलिस्ट वापस लौटता है?

यह माईलिस्ट को संशोधित करता है। इसलिए जब यह खत्म हो जाता है तो इसकी छंटनी की जाती है
हेलियोस


9
list.sort(Comparator.comparing(o -> o.getDateTime()));

तुनकी से जावा 8 लैम्ब्डा का उपयोग करते हुए सबसे अच्छा जवाब IMHO


8

यह देखते हुए MyObjectएक है कि DateTimeएक साथ सदस्य getDateTime()विधि, आप एक सॉर्ट कर सकते हैं ArrayListकि शामिल MyObjectद्वारा तत्वों DateTimeइस तरह की वस्तुओं:

Collections.sort(myList, new Comparator<MyObject>() {
    public int compare(MyObject o1, MyObject o2) {
        return o1.getDateTime().lt(o2.getDateTime()) ? -1 : 1;
    }
});

क्या होगा अगर मैं मौजूदा सिस्टम समय के आधार पर ऑर्डर करना चाहता हूं।
उपयोगकर्ता 3

5

इस तरह मैंने हल किया:

Collections.sort(MyList, (o1, o2) -> o1.getLastModified().compareTo(o2.getLastModified()));

आशा है कि यह आपकी मदद करेगा।


कैसे इसे तारीख से रिवर्स करने के लिए?
ज़ोंबी

2

जावा 1.8 की शुरुआत के साथ, इस तरह की समस्याओं को हल करने में धाराएँ बहुत उपयोगी हैं:

Comparator <DateTime> myComparator = (arg1, arg2) 
                -> {
                    if(arg1.lt(arg2)) 
                       return -1;
                    else if (arg1.lteq(arg2))
                       return 0;
                    else
                       return 1;
                   };

ArrayList<DateTime> sortedList = myList
                   .stream()
                   .sorted(myComparator)
                   .collect(Collectors.toCollection(ArrayList::new));

1

यहाँ सभी उत्तर मुझे एक साधारण समस्या के लिए गैर-जटिल रूप से जटिल लगे (कम से कम एक अनुभवी जावा डेवलपर, जो मैं नहीं हूँ)। मेरे पास एक समान समस्या थी और इस (और अन्य) समाधानों पर विचार किया गया था, और हालांकि उन्होंने एक संकेत प्रदान किया, एक शुरुआत के लिए जो मैंने ऊपर कहा गया था। मेरा समाधान, इस बात पर निर्भर करता है कि वस्तु में आपकी तिथि कहाँ है, इस मामले में, तिथि वस्तु का पहला तत्व है [] जहाँ डेटावेअर आपकी वस्तुओं से युक्त ArrayList है।

Collections.sort(dataVector, new Comparator<Object[]>() {
    public int compare(Object[] o1, Object[] o2) {
        return ((Date)o1[0]).compareTo(((Date)o2[0]));
    }
});

6
आपका उत्तर यहां अन्य उत्तरों की तुलना में कम जटिल या अधिक सही कैसे है? मेरी राय में, उदाहरण के लिए व्हाइटफैंग 32 का जवाब बहुत ही समान और अधिक संक्षिप्त है।
amotzg

थोड़ी देर के लिए दूर हो गया, इसलिए प्रतिक्रिया नहीं देखी, लेकिन फिर से, बेहतर देर से कभी नहीं। मुझे लगता है कि व्हाइटफैंग के जवाब में संक्षिप्तता मेरे (तब) अनुभवहीन जावा डेवलपर की आंखों के लिए इसकी खामी थी! मेरी प्रतिक्रिया में टाइपकास्टिंग का समावेश क्लीनिक (मेरे दिमाग में तब कम से कम) था। जो कुछ बचा है वह यह है कि आपने यह दावा किया है कि मेरा उत्तर दूसरों की तुलना में अधिक सही था? भाप छोड़ कर मुझे लगता है .. सब माफ है!
नेपालुज

O.getDateTime () टाइपिंग के बारे में नहीं था, यह एक DateTimeऑब्जेक्ट के ओपी विवरण के बारे में है जो किसी अन्य ऑब्जेक्ट के अंदर निहित है। यदि यह केवल Dateया DateTimeवस्तुएं होती हैं , तो पहली जगह में Comparableकोई आवश्यकता नहीं थी Comparator
amotzg

कहने का मतलब यह नहीं है कि आपका उत्तर कम सही है या कम अच्छा है। मैं सिर्फ मुझे जानकारी की तलाश में था ताकि मुझे इसे बेहतर ढंग से समझने में मदद मिल सके। मुझे खेद है अगर यह अन्यथा प्रतीत होता है।
amotzg

0

यह एक पुरानी प्रतिक्रिया हो सकती है लेकिन मैं एक तुलनित्र है कि एक को सॉर्ट होगा बनाने के लिए इस पोस्ट से कुछ उदाहरण का इस्तेमाल किया ArrayListकी HashMap<String, String>सूची में एक वस्तु से, टाइमस्टैम्प जा रहा है कि।

मेरे पास ये वस्तुएं हैं:

ArrayList<Map<String, String>> alList = new ArrayList<Map<String, String>>();

मानचित्र वस्तुएँ इस प्रकार हैं:

Map<String, Object> map = new HashMap<>();
        // of course this is the actual formatted date below in the timestamp
        map.put("timestamp", "MM/dd/yyyy HH:mm:ss"); 
        map.put("item1", "my text goes here");
        map.put("item2", "my text goes here");

वह मैपिंग वह है जिसका उपयोग मैं अपने सभी ऑब्जेक्ट्स को सरणी सूची में, alList.add(map)फ़ंक्शन का उपयोग करके , लूप के भीतर करने के लिए करता हूं ।

अब, मैंने अपना खुद का तुलनित्र बनाया:

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

 public class DateSorter implements Comparator {
     public int compare(Object firstObjToCompare, Object secondObjToCompare) {
    String firstDateString = ((HashMap<String, String>) firstObjToCompare).get("timestamp");
    String secondDateString = ((HashMap<String, String>) secondObjToCompare).get("timestamp");

    if (secondDateString == null || firstDateString == null) {
        return 0;
    }

    // Convert to Dates
    DateTimeFormatter dtf = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");
    DateTime firstDate = dtf.parseDateTime(firstDateString);
    DateTime secondDate = dtf.parseDateTime(secondDateString);

    if (firstDate.isAfter(secondDate)) return -1;
    else if (firstDate.isBefore(secondDate)) return 1;
    else return 0;
    }
}

मैं अब किसी भी समय एरेनेटर को कॉल कर सकता हूं और यह मेरे एरे को सॉर्ट करेगा, मुझे लेटेस्ट टाइमस्टैम्प पोजिशन 0 (लिस्ट में सबसे ऊपर) और लिस्ट के अंत में सबसे शुरुआती टाइमस्टैम्प देगा। नए पदों को मूल रूप से शीर्ष पर रखा जाता है।

Collections.sort(alList, new DateSorter());

इससे किसी को मदद मिल सकती है, यही वजह है कि मैंने इसे पोस्ट किया है। तुलना () फ़ंक्शन के भीतर रिटर्न स्टेटमेंट पर विचार करें। परिणाम 3 प्रकार के होते हैं। रिटर्निंग 0 अगर वे समान हैं, तो रिटर्निंग> 0 अगर पहली डेट दूसरी डेट से पहले है और रिटर्निंग <0 है तो पहली डेट दूसरी डेट के बाद की है। यदि आप चाहते हैं कि आपकी सूची उलट हो, तो बस उन दो रिटर्न स्टेटमेंट को स्विच करें! सरल =]


मैं इस पर एक टिप्पणी जोड़ना चाहता था। बेशक, सरणी सूची को संभालते समय "NullPointerException" हैं (रिटर्न 0 स्टेटमेंट दिया गया है)। इसलिए आपको उन्हें संभालना होगा क्योंकि प्रत्येक मामला अलग होगा। उदाहरण के लिए 0 ऑब्जेक्ट्स के साथ एक सूची NullPointerException उत्पन्न करेगी, या 1 ऑब्जेक्ट के साथ एक सूची!
ब्रैंडन

0

तर्क में ArrayList पास करें।

    private static void order(ArrayList<Object> list) {

    Collections.sort(list, new Comparator() {

        public int compare(Object o2, Object o1) {

            String x1 =  o1.Date;
            String x2 =  o2.Date;

                return  x1.compareTo(x2);

        }
    });
}

0

तारीखों की पहचान करने के लिए नीचे दिए गए दृष्टिकोण का उपयोग करें

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");

boolean  decendingOrder = true;
    for(int index=0;index<date.size() - 1; index++) {
        if(simpleDateFormat.parse(date.get(index)).getTime() < simpleDateFormat.parse(date.get(index+1)).getTime()) {
            decendingOrder = false;
            break;
        }
    }
    if(decendingOrder) {
        System.out.println("Date are in Decending Order");
    }else {
        System.out.println("Date not in Decending Order");
    }       
}   

1
यह सवाल का जवाब नहीं लगता है। और कृपया लंबे पुराने और कुख्यात परेशान करने वाले SimpleDateFormatवर्ग का उपयोग करने के लिए युवाओं को न सिखाएं । कम से कम पहले विकल्प के रूप में नहीं। और बिना किसी आरक्षण के नहीं। आज हमारे पास java.timeआधुनिक जावा तिथि और समय एपीआई और इसके बहुत बेहतर हैं DateTimeFormatter
ओले वीवी

0

दिनांक वर्ग पहले से ही तुलनित्र इंटरफ़ेस लागू करता है। मान लें कि आपके पास नीचे का वर्ग है:

public class A {

    private Date dateTime;

    public Date getDateTime() {
        return dateTime;
    }

    .... other variables

}

और मान लें कि आपके पास ए ऑब्जेक्ट्स की एक सूची है List<A> aList, आप इसे आसानी से जावा 8 के स्ट्रीम एपीआई (नीचे स्निपेट) के साथ सॉर्ट कर सकते हैं:

import java.util.Comparator;
import java.util.stream.Collectors;

...

aList = aList.stream()
        .sorted(Comparator.comparing(A::getDateTime))
        .collect(Collectors.toList())

-1

भविष्य के दर्शकों, मुझे लगता है कि यह सबसे सरल उपाय है, यदि आपके मॉडल में एक स्ट्रिंग प्रकार की तारीख (उदाहरण के लिए "2020-01-01 10:00:00") है, तो नीचे दिए गए दिनांक तक डेटा को सॉर्ट करने के लिए निम्न पंक्ति लिखें सबसे पुराने के लिए नवीनतम:

Collections.sort(messages, (o1, o2) -> o2.getMessageDate().compareTo(o1.getMessageDate()));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.