3

I have a class

public class SMS 
{
    public String addr;
    public String body;
    public String type;
    public String timestamp;
}

Now I have made an arrayList of objects

ArrayList<SMS> temp = new ArrayList<SMS>();

I have added the values. Now I want to sort the arrayList with respect to the timestamp.

How do I sort the arrayList in ascending/descending order with respect to the timestamp?

airbourne
  • 119
  • 1
  • 3
  • 11

4 Answers4

8
Collections.sort(temp);

will sort a collection of Comparable objects, so class SMS has to implement Comparable<SMS> :

public class SMS implementes Comparable<SMS>
{
    public String addr;
    public String body;
    public String type;
    public String timestamp;

    @Override
    public int compareTo(SMS other) {
       //for instance
       return addr.compareTo( other.addr );
    }
}

It is usually a good practice, when implementing Comparable to also implement equals() and hashcode() so that equality between objects is consistent with their comparison. Also, you should add some protection against null values :

public class SMS implements Comparable<SMS>
{
    public String addr;
    public String body;
    public String type;
    public String timestamp;

    @Override
    public int compareTo(SMS other) {
       //for instance
       if( addr == null ) {
           return Integer.MAX_VALUE;
       }
       return addr.compareTo( other.addr );
    }

    @Override
    public boolean equals(Object other) {
       //for instance
       if( other instanceof SMS ) {
          if( addr == null && ((SMS) other) != null ) {
              return false;
          }
          return addr.equals(((SMS) other).addr);
       } else {
          return false;
       }
       return addr.compareTo( other.addr );
    }

    @Override
    public int hashcode() {
       //for instance
       if( addr == null ) {
           return 0;
       }
       return addr.hashcode();
    }
}
Snicolas
  • 37,840
  • 15
  • 114
  • 173
  • Is that the correct answer ? A few more upvotes would get me enlightened : http://stackoverflow.com/help/badges/19/enlightened – Snicolas Apr 13 '14 at 10:34
5

To compare Strings containing timestamps you need to first parse them to long Long.parseLong(timestamp) and then compare numeric value using Long.compare(x,y).

So try maybe with Collections.sort(yorList, yourOwnComparator) like

Collections.sort(temp, new Comparator<SMS>() {
    @Override
    public int compare(SMS o1, SMS o2) {
        return Long.compare(Long.parseLong(o1.timestamp), 
                            Long.parseLong(o2.timestamp));
    }
});

If you can change type of timestamp to long this code could look like

Collections.sort(temp, new Comparator<SMS>() {
    @Override
    public int compare(SMS o1, SMS o2) {
        return Long.compare(o1.timestamp, o2.timestamp);
    }
});

In Java8 you can even use lambdas to shorten code even more

Collections.sort(temp, (SMS o1, SMS o2) -> Long.compare(o1.timestamp, o2.timestamp));

or even

Collections.sort(temp, (o1,  o2) -> Long.compare(o1.timestamp, o2.timestamp));
Pshemo
  • 122,468
  • 25
  • 185
  • 269
  • That's a good alternative, with some protection against o1 and/or o2 being null. – Snicolas Apr 13 '14 at 06:25
  • @Snicolas True. To avoid NPE OP would have to make sure that `timestamp` is not `null`. But I think that letting `timestamp` be `null` may be bigger issue so throwing NPE in this case would be informing that somewhere (earlier) in code exists a way/bug which lets timestamp be `null`s. Decision where to handle it belongs to OP. – Pshemo Apr 13 '14 at 07:35
0

Use Comparable (see example here), it should be something like this:

public class SMS implements Comparable<SMS>{

    ....

    public int compareTo(SMS compareSms) { 
        return this.timestamp.compareTo(compareSms.timestamp);
    }
}
Snicolas
  • 37,840
  • 15
  • 114
  • 173
Mzf
  • 5,210
  • 2
  • 24
  • 37
0

This is the general testing code:

ArrayList<SMS> temp = new ArrayList<SMS>();

// testing values
SMS a = new SMS();
a.setTime("a time");
SMS b = new SMS();
b.setTime("b time");
SMS c = new SMS();
c.setTime("c time");
temp.add(a);
temp.add(b);
temp.add(c);

// descending sort
Collections.sort(temp, new Comparator<SMS>() {
    public int compare(SMS text1, SMS text2) {
        // compare timestamps from the SMSs
        return text2.getTime().compareTo(text1.getTime());
    }
});

// print it out to test
for (SMS sms : temp) {
    System.out.println(sms.getTime());
}

If I want to change it from ascending to descending, I would simply need to switch the way I compare the text messages. Look at this:

return text2.getTime().compareTo(text1.getTime()); // descending
return text1.getTime().compareTo(text2.getTime()); // ascending

Note: I assume that getTime() returns the timestamp of the text message, and you need to add this import statement to your class: import java.util.Collections; or just import java.util.*;

To use the getTime() and setTime(String timestamp) methods, your class may look like this:

public class SMS 
{
    public String addr;
    public String body;
    public String type;
    public String timestamp;

    public void setTime(String timestamp) {
        this.timestamp = timestamp;
    }

    public String getTime() {
        return timestamp;
    }
}
Michael Yaworski
  • 13,410
  • 19
  • 69
  • 97