HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Custom sorting of dates

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
customsortingdates

Problem

I have implemented a class which implements a list of my custom DateObj. I have sorted the list in a peculiar manner based on the current month. I achieved my desired results, but I'm required to call Collections.sort() four times to achieve it. I feel this could be improved. Any thoughts?

//Custom Date Object
public class DateObj {

private int year;
private int month;
private int date;

DateObj(int year, int month ,int date){
    this.year = year;
    this.month = month;
    this.date = date;
}

public Integer getYear() {return year;}
public Integer getMonth() {return month;}
public Integer getDate() {return date;}
}


The custom sort class:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CustomListSort {
 static List list = new ArrayList<>();

public static void main(String a[]){

createRandomDateObjs();

Integer CURRENTMONTH = 6;

//Sort Months Descending
Collections.sort(list,(arg0,arg1)-> arg1.getMonth().compareTo(arg0.getMonth()));

//Sort by keeping the object with nearest largest next month first
Collections.sort(list,(arg0,arg1)->CURRENTMONTH.compareTo(arg0.getMonth()));

//Sort the months which were pushed back in an ascending order.
Collections.sort(list,(arg0,arg1)->(arg0.getMonth()(arg0.getMonth() == arg1.getMonth())  ? arg0.getDate().compareTo(arg1.getDate()) : 0);

System.out.println("\nDESIRED OUTPUT");
System.out.println("\nMM - DD - YYYY \n");

for(int i = 0 ; i<list.size();i++)
    System.out.println(list.get(i).getMonth() +" - "+list.get(i).getDate()+" - "+list.get(i).getYear());        
}

static void createRandomDateObjs(){
    for(int i = 0 ; i<20 ; i++){
        int y = 1980;
            y+=(int)(Math.random()*55);
        int m = (int) (Math.random()*11);
        int d = (int) (Math.random()*30);
        list.add(new DateObj(++y,++m,++d)); //Pre-increment to change 0's to 1's
}
}


Initially I had implemented it using Comparators but the Lambda made the code much cleaner.

D

Solution

A Comparator is the correct approach, you just need to mod the month by the current month before comparing them. The easiest way to do this is to introduce a static variable currentMonth to hold the current month for all instances of DateObj.

Add DateObj.setCurrentMonth(CURRENTMONTH); to your Main, and use the code below:

//Custom Date Object
class DateObj implements Comparable{

    private int year;
    private int month;
    private int date;
    private static int currentMonth;

    DateObj(int year, int month ,int date){
      this.year = year;
      this.month = month;
      this.date = date;
    }

    public Integer getYear() {return year;}
    public Integer getMonth() {return month;}
    public Integer getDate() {return date;}
    public Integer getCurrentMonth() { return DateObj.currentMonth;}
    public static void setCurrentMonth(int currentMonth){
        DateObj.currentMonth = currentMonth;
    }

    @Override
    public int compareTo(DateObj o) {
        int months = (month+(12-currentMonth))%12 - (o.month+(12-currentMonth))%12;
        if(months == 0)
            return this.date-o.date;
        else{
            return months;
        }
    }
}


EDIT: An alternative approach is to simply define the Comparator in your main body. This avoids the use a static value to hold currentMonth:

Collections.sort(list, (o1,o2)->{
            int months = (o1.getMonth()+(12-CURRENTMONTH))%12 - (o2.getMonth()+(12-CURRENTMONTH))%12;
            if(months == 0)
                return o1.getDate()-o2.getDate();
            else{
                return months;
            }
    });


Thanks to Mr.Wiggles for the recommendation.

Code Snippets

//Custom Date Object
class DateObj implements Comparable<DateObj>{

    private int year;
    private int month;
    private int date;
    private static int currentMonth;

    DateObj(int year, int month ,int date){
      this.year = year;
      this.month = month;
      this.date = date;
    }

    public Integer getYear() {return year;}
    public Integer getMonth() {return month;}
    public Integer getDate() {return date;}
    public Integer getCurrentMonth() { return DateObj.currentMonth;}
    public static void setCurrentMonth(int currentMonth){
        DateObj.currentMonth = currentMonth;
    }

    @Override
    public int compareTo(DateObj o) {
        int months = (month+(12-currentMonth))%12 - (o.month+(12-currentMonth))%12;
        if(months == 0)
            return this.date-o.date;
        else{
            return months;
        }
    }
}
Collections.sort(list, (o1,o2)->{
            int months = (o1.getMonth()+(12-CURRENTMONTH))%12 - (o2.getMonth()+(12-CURRENTMONTH))%12;
            if(months == 0)
                return o1.getDate()-o2.getDate();
            else{
                return months;
            }
    });

Context

StackExchange Code Review Q#117757, answer score: 6

Revisions (0)

No revisions yet.