This discussion is archived
1 2 Previous Next 18 Replies Latest reply: Sep 7, 2008 5:02 AM by 796254 RSS

Sorting a date represented in three integers.

807589 Newbie
Currently Being Moderated
Hey,

I have an other question. I want to sort a collection on the data. In my collection I have three integers representing the date (int matchDay, int matchMonth, int matchYear)

The constructor for the Collection<Comment> is:
public Comment(int matchID, int matchDay, int matchMonth, int matchYear, String namePlayer, String comments) 
I want the comments which happened at the beginning at the bottom and the comments which just happened at the top. So, I want to sort in a decending order.

I tried to sort with severly options. The most likely which I thought was to succed, is this code:
// To sort Comments selection

public Collection<Comment> sortCommentCollection(Collection<Comment> comments) {

    Collection<Comment> backup = new ArrayList<Comment>();


    String DATE_FORMAT = "yyyy-MM-dd";

    java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(DATE_FORMAT);

    Calendar c1 = Calendar.getInstance();

    Calendar c2 = Calendar.getInstance();



    int year = 1000, month = 00, day = 00, x = 0;



    boolean attached = false;

    for(Comment c : comments) {

        // remember months are zero-based : 0 jan 1 feb ... 

        c1.set(year, month, day);

        c2.set(c.getMatchYear(), c.getMatchMonth() , c.getMatchDay());



        if (c1.before(c2) && !attached) {

            // Remove 'older' comment before adding this comment

            backup.remove(x - 1);

            Comment temporary = new Comment(c.getMatchID(), c.getMatchDay(), c.c.getMatchMonth(), c .c.getMatchYear(), c.getNamePlayer(), c.getComments());

            backup.add(temporary);

            attached = true;

            }

        if (c1.after(c2) && !atteched) {

            Comment temporary = new Comment(c.getMatchID(), c.getMatchDay(), c.c.getMatchMonth(), c .c.getMatchYear(), c.getNamePlayer(), c.getComments());

            backup.add(temporary);

            attached = true;

        }

        if (c1.equals(c2)) {

            // To prevent double entries

            backup.remove(x - 1);

        }



        year = c.getMatchYear();

        month = c.getMatchMonth();

        day = c.getMatchDay();



        attached = false;

        x++;

    }


        return backup;

}
But this did not work either. Does anyboedy have a suggestion? You would help me a lot! Thanks in advance.
  • 1. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    Write a Comparator and use Collections.sort(List, Comparator);

    Here is an (untested) possible Comparator you could use:
    public class CommentComparator implements Comparator {
    
        public int compare(final Object o1, final Object o2) 
        throws ClassCastException {
            final Comment c1 = (Comment) o1;
            final Comment c2 = (Comment) o2;
            
            if (c1.getDate().before(c2.getDate())) {
                return -1;
            } else if (c2.getDate().after(c2.getDate())) {
                return 1;
            } else {        
                return 0;
            }            
        }
    }
    If I were in your place, I would also consider just making before() and after() methods on Comment.
  • 2. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    Thanks for the suggestion. Because I did not have an getDate() method I just used c1.getMatchMonth(). To quickly test it I wanted only to sort on the months. So the code will be:
    import java.util.*;
    
    public class CommentComparetor implements Comparator {
    
         public int compare(final Object o1, final Object o2)
                   throws ClassCastException {
              final Comment c1 = (Comment) o1;
              final Comment c2 = (Comment) o2;
    
              if (c1.getMatchMonth() < c2.getMatchMonth()) {
                   return -1;
              } else if (c2.getMatchMonth() > c2.getMatchMonth()) {
                   return 1;
              } else {
                   return 0;
              }
         }
    }
    But now he throws an NullPointerException on the line
     if (c1.getMatchMonth() < c2.getMatchMonth())
    I tried to check it with
    System.out.println(c1.getMatchMonth());
    but he did not printed anything in the console. And yes I put the System.out before the if-statements :)

    Still any suggestion?

    Edited by: Vinvar on Sep 5, 2008 12:21 PM
  • 3. Re: Sorting a date represented in three integers.
    masijade Explorer
    Currently Being Moderated
    Create a Calendar object. Set month, year, and day using the three numbers, and extract a Date Object and place it into an array. Sort the Array, then set the Calendar using the sorted Dates and extract the month, year, and day again.
  • 4. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    If you have an NPE, your collection contains a null Comment object.
    Also, please note my original Comparator had a bug in the } else if {
    line. You need to compare c1 to c2, not c2 to c2.
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    
    
    public class Comment {
    
        private final long commentCreated;
        
        private final DateFormat dateFormatter = 
            new SimpleDateFormat("yyyy/MM/dd");
        
        public Comment(final int year, final int month, final int day) {
            final Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.YEAR, year);
            calendar.set(Calendar.MONTH, month - 1);
            calendar.set(Calendar.DAY_OF_MONTH, day);
            this.commentCreated = calendar.getTimeInMillis();
        }
        
        public Date getCreationDate() {
            return new Date(this.commentCreated);
        }
        
        public String toString() {
            return this.dateFormatter.format(new Date(this.commentCreated));
        }
    }
    import java.util.Comparator;
    
    public class CommentComparator implements Comparator {
    
        public int compare(final Object o1, final Object o2) 
        throws ClassCastException {
            final Comment c1 = (Comment) o1;
            final Comment c2 = (Comment) o2;
            
            if (c1.getCreationDate().before(c2.getCreationDate())) {
                return -1;
            } else if (c1.getCreationDate().after(c2.getCreationDate())) {
                return 1;
            } else {
                return 0;
            }            
        }
    }
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class CommentTest {
    
        public static void main(final String[] argv) {
            final List comments = new ArrayList();
            comments.add(new Comment(1990, 12, 8));
            comments.add(new Comment(1974, 5, 3));
            comments.add(new Comment(2001, 1, 4));
            //comments.add(null);  Uncomment this line for NPE
            Collections.sort(comments, new CommentComparator());
            System.out.println(comments);
            
        }
    }
  • 5. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    Wow, thanks a lot!

    I am a lucky person that you would write it all out for me. I am in your dept!

    The sorter does work now, but he still thinks that 17 < 1 (for the days). I guess that I could reprogram that if I write my own before and after method? Or is it that my int MatchDay is 1 instead of 01? If that is the case, can you make an integer which excists of a couple of zero's before any other number?
  • 6. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    Also, please note my original Comparator had a bug in the } else if {
    line. You need to compare c1 to c2, not c2 to c2.
  • 7. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    Yeah, I noticed that. But if I use the full code from the last message, it does not sort on days (so 17 < 1).

    But thanks for pointing it out again!
  • 8. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    Vinvar wrote:
    I want to sort a collection on the data. In my collection I have three integers representing the date (int matchDay, int matchMonth, int matchYear)
    Just add another integer representing roughly the days since Jesus' birth, then you can simply sort by that.
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Random;
    
    public class Comment
    {
         private final int _year;
         private final int _month;
         private final int _day;
         private final int _jesus;
         private final String _string;
         
         public Comment(int year, int month, int day)
         {
              _year = year;
              _month = month;
              _day = day;
              // calculate approx. days since Jesus' birth
              _jesus = (_year * 12 + _month) * 31 + _day;
              _string = String.format("%02d-%02d-%04d", _month, _day, _year);
         }
    
         public int getMatchYear()
         {
              return _year;
         }
    
         public int getMatchMonth()
         {
              return _month;
         }
    
         public int getMatchDay()
         {
              return _day;
         }
    
         public int getJesus()
         {
              return _jesus;
         }
         
         @Override
         public String toString()
         {
              return _string;
         }
    }
    
    class DescendingComments implements Comparator<Comment>
    {
         @Override
         public int compare(Comment o1, Comment o2)
         {
              return o2.getJesus() - o1.getJesus();
         }
    }
    
    class TestComment
    {
         public static void main(String[] args)
         {
              List<Comment> comments = new ArrayList<Comment>();
              Random rand = new Random();
              for (int i = 0; i < 10; ++i)
              {
                   comments.add(new Comment(
                             rand.nextInt(2000),
                             rand.nextInt(12) + 1,
                             rand.nextInt(31) + 1));
              }
              System.out.println(comments);
              Collections.sort(comments, new DescendingComments());
              System.out.println(comments);
         }
    }
  • 9. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    If you want descending order, switch the before and after calls in the comparator.

    It most certainly does work on days. This test:
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
     
    public class CommentTest {
     
        public static void main(final String[] argv) {
            final List comments = new ArrayList();
            comments.add(new Comment(1990, 12, 17));
            comments.add(new Comment(1990, 12, 1));
            Collections.sort(comments, new CommentComparator());
            System.out.println(comments);
        }
    }
    Generates these results:
    [1990/12/01, 1990/12/17]
  • 10. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    SunFred wrote:
    Just add another integer representing roughly the days since Jesus' birth, then you can simply sort by that.
    And how do you propose to handle leap years? Why rewrite functionality that already exists? Why add artificial, unncessary properties to a class?
  • 11. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    es5f2000 wrote:
    SunFred wrote:
    Just add another integer representing roughly the days since Jesus' birth, then you can simply sort by that.
    And how do you propose to handle leap years?
    We don't need to know EXACTLY the number of days since Jesus' birth, only ROUGHLY. No year has more than 12 months, and no month has more than 31 days. That's why the formula jesus = (year * 12 + month) * 31 + day already accounts for leap years and is perfect FOR THE PURPOSE OF SORTING.
    Why add artificial, unncessary properties to a class?
    To make it easier (less error prone and more efficient) to sort them.

    Now, if you don't like Jesus as part of the interface, you are probably right. Let's refactor:
    public class Comment implements Comparable<Comment>
    {
         private final int _year;
         private final int _month;
         private final int _day;
         private final int _jesus;
         private final String _string;
         
         public Comment(int year, int month, int day)
         {
              _year = year;
              _month = month;
              _day = day;
              // calculate approx. days since Jesus' birth
              _jesus = (_year * 12 + _month) * 31 + _day;
              _string = String.format("%02d-%02d-%04d", _month, _day, _year);
         }
    
         public int getMatchYear()
         {
              return _year;
         }
    
         public int getMatchMonth()
         {
              return _month;
         }
    
         public int getMatchDay()
         {
              return _day;
         }
    
         @Override
         public String toString()
         {
              return _string;
         }
    
         @Override
         public int compareTo(Comment that)
         {
              return this._jesus - that._jesus;
         }
    }
    
    class DescendingComments implements Comparator<Comment>
    {
         @Override
         public int compare(Comment o1, Comment o2)
         {
              return o2.compareTo(o1);
         }
    }
    Better?
  • 12. Re: Sorting a date represented in three integers.
    796254 Newbie
    Currently Being Moderated
    WTF is this?

    Doing it this way is so NOT object-oriented that it hurts.

    Java's an object-oriented language. Objects are supposed to encapsulate and hide complexity. That's what the java.util.Date is doing for you. If you insist on seeing that abstraction as three integers I'd say you're making a HUGE mistake. Go back to writing VB or C. Objects are not for you.

    %
  • 13. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    Good advice, but java.util.Date has been deprecated for over 10 years (since Java 1.1).
  • 14. Re: Sorting a date represented in three integers.
    807589 Newbie
    Currently Being Moderated
    SunFred wrote:
    Good advice, but java.util.Date has been deprecated for over 10 years (since Java 1.1).
    ? I don't get deprecation warnings from java.util.Date, and the javadoc
    doesn't specify it as being deprecated. Perhaps you'd like to share with
    us what makes you think it has been deprecated?
1 2 Previous Next