简体   繁体   中英

Sort keys which are date entries in a hashmap

I have a hashMap which has the following values as key value(sql date, integer) pairs:

a.put("31-05-2011",67);
a.put("01-06-2011",89);
a.put("10-06-2011",56);
a.put("25-05-2011",34);

when i try to sort the hashMap based on the keys using: Map modified_a=new TreeMap(a); and display the keys it is as follows:

01-06-2011,10-06-2011,25-05-2011, 31-05-2011

but I want the keys to be sorted as

31-05-2011,25-05-2011,01-06-2011 ,10-06-2011

I can see that the values are being sorted based on the first 2 digits( which is the date value) but I need the month value to also be considered and sort based on months first and then for each month sort the corresponding days. Any clues??

The best solution IMO would be to use a different data type for the keys - a data type which actually represents a date, and which sorts in natural date order. Unless otherwise constrained, I'd use Joda Time 's LocalDate type, which represents exactly what you want (just a date, not a date/time etc).

If you really want to use string keys but can change the format of them, you could use a yyyy-MM-dd format, which is naturally sortable.

Alternatively, you could pass in a Comparator<String> to the TreeMap constructor, where the comparator is one which parses two strings when it's asked to compare them, and performs the comparison based on the parsed year/month/day values. There isn't a constructor which takes both a custom comparator and an existing map though, so you'd need something like:

Map<String, Integer> modified = new TreeMap<String, Integer>(customComparator);
modified.putAll(a);

This approach will be relatively slow if you have a lot of data (due to the repeated parsing), and slightly fiddly to write - I'd use a more appropriate data type if you possibly can.

You can use like

Map<Date, Integer> m = new HashMap<Date, Integer>(); 

    DateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy");

    m.put(new java.sql.Date(dateFormat.parse("31-05-2011").getTime()),67);
    m.put(new java.sql.Date(dateFormat.parse("01-06-2011").getTime()),89);
    m.put(new java.sql.Date(dateFormat.parse("10-06-2011").getTime()),56);
    m.put(new java.sql.Date(dateFormat.parse("25-05-2011").getTime()),34);


    Map<Date, Integer> m1 = new TreeMap(m);
    DateFormat df = new SimpleDateFormat("dd/MM/yyyy");

    for (Map.Entry<Date, Integer> entry : m1.entrySet())
    {
        System.out.println(df.format(entry.getKey()));
    }

I had a requirement to reverse sort the dates (most recent date first). I made it work by using the code below:

Map<Date, Integer> dateMap = new TreeMap<Date, Integer>(new Comparator<Date>() {
    public int compare(Date date1, Date date2) {
        return date2.compareTo(date1);
    }
});

Calling dateMap.keySet() will result in a Set with keys, in which the most recent dates are returned first.

You have to pass a custom comparator to the TreeMap constructor, that will compare your keys as dates instead of strings(or use java.util.Date as key, in which case it will happen out of box as date implements Comparable).

Create comparator:

public class DateComparator implements Comparator<Date> {
    public int compare(Date date1, Date date2) {
        return date1.compareTo(date2);
    }
}

And use comparator with TreeMap

Map<Date, Integer> comparedDates = new TreeMap<Date, Integer>(new DateComparator());
// here fill you <Date, Integer> map like:
comparedDates.put(new Date(System.currentTimeMillis()), 123);

All dates in you Map will be sorted.

You may want to use a TreeMap instead of a HashMap and create the Map with a custom Comparator that provides the sorting.

Here's a draft for an anonymous comparator (that does not parse the String into a comparable date object):

new Comparator<String>() {

    @Override
    public int compare(String date1, String date2) {
        // skipping tests! Assuming, all date are well formatted

        String[] parts1 = date1.split("-");
        String[] parts2 = date2.split("-");

        String reordered1 = parts1[2] + parts1[1] + parts1[0];
        String reordered2 = parts2[2] + parts2[1] + parts2[0];

        return reordered1.compareTo(reordered2);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM