-1

I am creating an android application where I need to sort objects according to date. The date is stored as a String in Customer Object. How can I do it?

I have already tried it using the Collection.sort() method but with no success.

public static Comparator<Customer> dateNewOld = new Comparator<Customer>() {
       @Override
       public int compare(Customer o1, Customer o2) {
           DateFormat f = new SimpleDateFormat("dd/MM/yyyy");
           try
           {
               return f.parse(o2.date).compareTo(f.parse(o1.date));
           }
           catch (ParseException e)
           {
               e.printStackTrace();
           }
           return 0;
       }
   };

I expect the output to be sorted ArrayList but it doesn't get sorted according to date.

My Date Format is 19.Jul.2019, but it’s giving me Unparseable Exception.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Anas khan
  • 175
  • 1
  • 3
  • 13
  • 1
    Please provide a full example, the data and your code for sorting are not there. – Karol Dowbecki Jul 19 '19 at 14:33
  • Code seems to be fine. By how much your dates are different. Are they different by days and months ? –  Jul 19 '19 at 14:34
  • If you put the date in format year/month/date, that may make it easier to sort. – SedJ601 Jul 19 '19 at 14:34
  • They are different by days.Its in dd/MM/yy format – Anas khan Jul 19 '19 at 14:35
  • Well, I suggest you convert the format you got to the format that leans itself to sorting. – SedJ601 Jul 19 '19 at 14:36
  • Or you can use Java LocalDate and it can do the work for you. – SedJ601 Jul 19 '19 at 14:37
  • How can i use LocaleDate – Anas khan Jul 19 '19 at 14:37
  • https://www.mkyong.com/java8/java-8-how-to-convert-string-to-localdate/ – SedJ601 Jul 19 '19 at 14:39
  • 1
    `DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/yyyy"); LocalDate date1 = LocalDate.parse("12/02/2019", dtf); LocalDate date2 = LocalDate.parse("12/03/2019", dtf); System.out.println(date1.compareTo(date2));` – SedJ601 Jul 19 '19 at 14:50
  • i Just saw that its Giving me Unparceable Exception – Anas khan Jul 19 '19 at 15:57
  • 1
    FYI, the troublesome date-time classes such as `java.util.Date`, `java.util.Calendar`, & `java.text.SimpleDateFormat` are now legacy, supplanted by the [*java.time*](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html) classes. Most *java.time* functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android (<26) in [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP). See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Jul 19 '19 at 21:36
  • 1
    Tip: Rewrite your `Customer` class to hold a `LocalDate` object rather than a mere string. – Basil Bourque Jul 19 '19 at 21:38
  • Please post the stack trace from your exception. It will tell us a whole lot about what’s going wrong. – Ole V.V. Jul 21 '19 at 07:02
  • [I downvoted because your question is missing exception details](http://idownvotedbecau.se/noexceptiondetails/) and [because lacking a minimal, reproducible example (formerly known as an MCVE) makes it hard to answer](http://idownvotedbecau.se/nomcve/). – Ole V.V. Jul 21 '19 at 07:05

6 Answers6

3

java.time

Use the java.time classes that supplant the troublesome legacy classes (java.util.Date, java.sql.Date, SimpleDateFormat). An implementation of the modern classes come with Android 26 and later.

Most of the java.time functionality is back-ported to Java 6 & Java 7 in the ThreeTen-Backport project. Further adapted for earlier Android (<26) in ThreeTenABP. See How to use ThreeTenABP….

LocalDate represents a date-only value, without time-of-day and without time zone.

package sortdates;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class SortDates {

    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        Comparator<MyData> comparator = Comparator.comparing(myData -> LocalDate.parse(myData.date, formatter));
        List<MyData> set = getMyData().stream()
                .sorted(comparator)
                .collect(Collectors.toList());
        set.forEach(myData -> System.out.println(myData.date));
    }

    private static Collection<MyData> getMyData() {
        return Arrays.asList(
                new MyData("01/01/2000"),
                new MyData("01/02/2000"),
                new MyData("03/01/2002"),
                new MyData("04/06/2001")
                );
    }

    public static class MyData{
        String date;

        public MyData(String date) {
            this.date = date;
        }
    }

}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Ezequiel
  • 3,477
  • 1
  • 20
  • 28
  • 2
    I added some explanatory text to your Answer. Stack Overflow is meant to be more than a snipped collection. You are expected to have some explanation of your code, its motivation, and its details. – Basil Bourque Jul 19 '19 at 21:35
2

LocalDate as your property

The best solution is to alter your Customer class to use LocalDate class as the type of your property.

Tip: Use a more descriptive name for your member fields that just date.

public class Customer {
    public LocalDate firstContact ; 
    …
}

Now your Comparator becomes quite simple, as the LocalDate class already implements the Comparable interface and its compareTo method.

public static Comparator< Customer > CustomerComparator = new Comparator< Customer >() 
{
    @Override
    public int compare( Customer c1 , Customer c2 ) {
        return ( c1.firstContact.compareTo( c2.firstContact ) ) ;
    }
};

If you cannot change the data type of your class property, see the correct Answer by Ezequiel.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

ArrayList sorting String_Dates and avoiding duplicates on adding.

Adding a new example to @Ezequiel post.

public class ArrayListSet {
    static ArrayList<String> list =  new java.util.ArrayList<String>();
    public static void main(String[] args) {
        String inputDatess = "15.10.2020,11.10.2020,12.10.2020,12.10.2020,18.10.2020,13.10.2020,14.10.2020,11.10.2020,"
                + "15.10.2020,15.10.2020,15.10.2020,16.10.2020,17.10.2020,18.10.2020,19.10.2020,20.10.2020,10.10.2020";
        
        String[] dates = inputDatess.split(",");
        for (int i = 0; i < dates.length; i++) {
            listCustomAdd(dates[i]);
        }
        System.out.println("ArrayList with Custom Funciton for Add:\n"+list);
        
        ArrayList<String> listSorted = getSortedDatesStrList(list.stream());
        System.out.println("Sorted ArrayList:\n"+listSorted);
    }
    public static ArrayList<String> getSortedDatesStrList(Stream<String> stream) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
        Comparator<String> comparator = Comparator.comparing(myData -> LocalDate.parse(myData, formatter));
        ArrayList<String> sortedList = (ArrayList<String>) stream
                .sorted(comparator)
                .collect(Collectors.toList());
        return sortedList;
    }
    public static void listCustomAdd(String dateStr) {
        if( !list.contains(dateStr) )
            list.add(dateStr);
    }
}

Example with Customed ArrayList to sort and avoid duplicates:

public class CustomArrayListSet {
    //static ArrayList<String> predefinedList =  new java.util.ArrayList<String>();
    static ArrayListCustomStr<String> customList = new ArrayListCustomStr<String>();
    public static void main(String[] args) {
        String inputDatess = "15.10.2020,11.10.2020,12.10.2020,12.10.2020,18.10.2020,13.10.2020,14.10.2020,11.10.2020,"
                + "15.10.2020,15.10.2020,15.10.2020,16.10.2020,17.10.2020,18.10.2020,19.10.2020,20.10.2020,10.10.2020";
        
        String[] dates = inputDatess.split(",");
        for (int i = 0; i < dates.length; i++) {
            customList.add(dates[i]);
        }
        System.out.println("Custom ArrayList with override Add Function:\n"+customList);
        
        customList.sortDatesStrList();
        System.out.println("Sorted ArrayList:\n"+ customList );
    }
}
class ArrayListCustomStr<T> implements Set<T> {
    @Override
    public String toString() {
        StringBuffer buffer = new StringBuffer("[");
        for (int i = 0; i < entries.size(); i++) {
            buffer.append(entries.get(i));
            if ( (i+1) < entries.size() ) buffer.append(", ");
        }
        buffer.append("]");
        return buffer.toString();
    }
    public void sortDatesStrList() {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
        Comparator<String> comparator = Comparator.comparing(myData -> LocalDate.parse(myData, formatter));
        ArrayList<String> sortedList = (ArrayList<String>) entries.stream()
                .sorted(comparator)
                .collect(Collectors.toList());
        entries = sortedList;
    }
    private ArrayList<String> entries;
    // Simple constructor using an array list for its entries.
    public ArrayListCustomStr() {
        super();
        entries = new ArrayList<String>();
    }
    public int size() {
        return entries.size();
    }
    public void clear() {
        entries.clear();
    }
    public boolean isEmpty() {
        return entries.isEmpty();
    }
    public Object[] toArray() {
        return entries.toArray();
    }
    public boolean add(Object o) {
        // Ignore existing entries to ensure Set interface contract
        if (entries.contains(o))
            return false;

        return entries.add((String) o);
    }
    public boolean contains(Object o) {
        return entries.contains(o);
    }
    public boolean remove(Object o) {
        return entries.remove(o);
    }
    @SuppressWarnings("unchecked")
    public boolean addAll(@SuppressWarnings("rawtypes") Collection c) {
        return entries.addAll(c);
    }
    public boolean containsAll(@SuppressWarnings("rawtypes") Collection c) {
        return entries.containsAll(c);
    }
    public boolean removeAll(@SuppressWarnings("rawtypes") Collection c) {
        return entries.removeAll(c);
    }
    public boolean retainAll(@SuppressWarnings("rawtypes") Collection c) {
        return entries.retainAll(c);
    }
    @SuppressWarnings("unchecked")
    public Iterator<T> iterator() {
        return (Iterator<T>) entries.iterator();
    }
    @SuppressWarnings("unchecked")
    public Object[] toArray(Object[] a) {
        return entries.toArray(a);
    }
}
Yash
  • 9,250
  • 2
  • 69
  • 74
0

As per mkyong

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Date date1 = sdf.parse("2009-12-31");
    Date date2 = sdf.parse("2010-01-31");

    System.out.println("date1 : " + sdf.format(date1));
    System.out.println("date2 : " + sdf.format(date2));

    if (date1.compareTo(date2) > 0) {
        System.out.println("Date1 is after Date2");
    }
Abbin Varghese
  • 2,422
  • 5
  • 28
  • 42
  • 1
    Please elaborate it with an example – Anas khan Jul 19 '19 at 14:37
  • All you have to do is change the format string. This is as straight forward as it gets. @Anaskhan – SedJ601 Jul 19 '19 at 14:41
  • As in the example, did you try with `SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); ` – Abbin Varghese Jul 19 '19 at 14:44
  • I still am unable to figure it out.Can you please change the example i gave for Ascending Order – Anas khan Jul 19 '19 at 14:46
  • My Date Format is 19.Jul.2019 , but its giving me Unparceable Exception – Anas khan Jul 19 '19 at 15:58
  • 1
    FYI, the troublesome date-time classes such as `java.util.Date`, `java.util.Calendar`, & `java.text.SimpleDateFormat` are now legacy, supplanted by the [*java.time*](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html) classes. Most *java.time* functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android (<26) in [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP). See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Jul 19 '19 at 21:36
0

Comparing o2 with o1 will sort your list in descending order.

You can use Collections.sort() as well as list.sort()

I have created a test class with a customer object. Hope this example will help.

package project;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class SortTest
{

    public static void main(String args[])
    {
        List<Customer> list = new ArrayList<>();
        list.add( new Customer( 1, "21/07/2019" ) );
        list.add( new Customer( 2, "19/06/2019" ) );
        list.add( new Customer( 3, "20/07/2019" ) );

        Collections.sort( list, dateNewOld );
        //list.sort( dateNewOld );

        print( list );
    }

    public static Comparator<Customer> dateNewOld = new Comparator<Customer>()
    {
        @Override
        public int compare( Customer o1, Customer o2 )
        {
            DateFormat f = new SimpleDateFormat( "dd/MM/yyyy" );
            try
            {
                return f.parse( o2.date ).compareTo( f.parse( o1.date ) );
            }
            catch ( ParseException e )
            {
                e.printStackTrace();
            }
            return 0;
        }
    };

    private static void print( List<Customer> list )
    {
        for ( Customer customer : list )
        {
            System.out.println(customer);
        }
    }

    static class Customer
    {
        final int id;
        final String date;

        Customer( int id, String date )
        {
            this.id = id;
            this.date = date;
        }

        @Override
        public String toString()
        {
            return "Customer{" +
                    "id=" + id +
                    ", date='" + date + '\'' +
                    '}';
        }
    }

}
0

I guess the problem is with how you compare the two Strings, here is a working example(in ascending order).

List<String> dateList = new ArrayList<>();
dateList.add("22/05/1995");
dateList.add("22/01/1995");
dateList.add("22/01/1994");
Comparator<String> dateNewOld = new Comparator<String>() {
  @Override
  public int compare(String o1, String o2) {
    DateFormat f = new SimpleDateFormat("dd/MM/yyyy");
    try {
      return f.parse(o1).compareTo(f.parse(o2));
    } catch (ParseException e) {
      e.printStackTrace();
    }
    return 0;
  }
};
dateList.sort(dateNewOld);
System.out.println(dateList);

PS: My guess is that your code is not sorting because of return 0 inside the comparator. Maybe your code is throwing an exception and you haven't seen console!

Mohamed Anees A
  • 4,119
  • 1
  • 22
  • 35
  • 1
    FYI, the troublesome date-time classes such as `java.util.Date`, `java.util.Calendar`, & `java.text.SimpleDateFormat` are now legacy, supplanted by the [*java.time*](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/package-summary.html) classes. Most *java.time* functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android (<26) in [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP). See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Jul 19 '19 at 21:36