0

Basically, what I am trying to achieve is to sort the final map in descending order. (the latest dates are in the beginning of the map).

I have the following method which takes an ArrayList of DtObjects as a parameter and a static discriminator string:

 public static <T> Map<T, List<String>> groupTimePeriods(List<DtObject> timePeriods, String groupProperty)
    {
        Map<T, List<String>> groupedTimePeriods = new TreeMap<>();
        if (timePeriods == null)
        {
            return groupedTimePeriods;
        }
        for (DtObject timePeriod : timePeriods)
        {
            GWT.log(groupedTimePeriods.toString());
            T groupPropertyValue = timePeriod.<T> getProperty(groupProperty);
            if (groupPropertyValue != null)
            {
                List<String> group = groupedTimePeriods.get(groupPropertyValue);
                if (group == null)
                {
                    groupedTimePeriods.put(groupPropertyValue, group = new ArrayList<>());
                }
                Long startTime = timePeriod.getProperty(Constants.TimePeriod.START_TIME);
                Long endTime = timePeriod.getProperty(Constants.TimePeriod.END_TIME);
                if (startTime != null || endTime != null)
                {
                    group.add(formatTimePeriod(startTime, endTime));
                }
            }
        }
        return groupedTimePeriods;
    }

I know DtObject might be really complicated but here all I need is just a simple Date object

T groupPropertyValue = timePeriod.<T> getProperty(groupProperty);

Returns Date.

For example when I put dates in ascending order it looks so well, there's no mess

ConsoleLogger.java:32 {}
ConsoleLogger.java:32 {Mon Sep 02 00:00:00 GMT+500 2019=[]}
ConsoleLogger.java:32 {Mon Sep 02 00:00:00 GMT+500 2019=[1:00-2:00]}
ConsoleLogger.java:32 {Mon Sep 02 00:00:00 GMT+500 2019=[1:00-2:00], Wed Sep 04 00:00:00 GMT+500 2019=[]}
ConsoleLogger.java:32 {Mon Sep 02 00:00:00 GMT+500 2019=[1:00-2:00], Wed Sep 04 00:00:00 GMT+500 2019=[], Fri Sep 06 00:00:00 GMT+500 2019=[]}
ConsoleLogger.java:32 {Mon Sep 02 00:00:00 GMT+500 2019=[1:00-2:00], Wed Sep 04 00:00:00 GMT+500 2019=[], Fri Sep 06 00:00:00 GMT+500 2019=[], Sat Sep 14 00:00:00 GMT+500 2019=[]}
ConsoleLogger.java:32 {Mon Sep 02 00:00:00 GMT+500 2019=[1:00-2:00], Wed Sep 04 00:00:00 GMT+500 2019=[], Fri Sep 06 00:00:00 GMT+500 2019=[], Sat Sep 14 00:00:00 GMT+500 2019=[], Tue Sep 17 00:00:00 GMT+500 2019=[]}

However, when I try to do the same thing but with the dates coming in descending order (timePeriods list) the whole map is messed up:

ConsoleLogger.java:32 {}
ConsoleLogger.java:32 {Wed Sep 25 00:00:00 GMT+500 2019=[]}
ConsoleLogger.java:32 {Tue Sep 17 00:00:00 GMT+500 2019=[], Wed Sep 25 00:00:00 GMT+500 2019=[]}
ConsoleLogger.java:32 {Sat Sep 14 00:00:00 GMT+500 2019=[], Tue Sep 17 00:00:00 GMT+500 2019=[], Wed Sep 25 00:00:00 GMT+500 2019=[]}
ConsoleLogger.java:32 {Fri Sep 06 00:00:00 GMT+500 2019=[], Sat Sep 14 00:00:00 GMT+500 2019=[], Tue Sep 17 00:00:00 GMT+500 2019=[], Wed Sep 25 00:00:00 GMT+500 2019=[]}
ConsoleLogger.java:32 {Wed Sep 04 00:00:00 GMT+500 2019=[], Fri Sep 06 00:00:00 GMT+500 2019=[], Sat Sep 14 00:00:00 GMT+500 2019=[], Tue Sep 17 00:00:00 GMT+500 2019=[], Wed Sep 25 00:00:00 GMT+500 2019=[]}
ConsoleLogger.java:32 {Mon Sep 02 00:00:00 GMT+500 2019=[1:00-2:00], Wed Sep 04 00:00:00 GMT+500 2019=[], Fri Sep 06 00:00:00 GMT+500 2019=[], Sat Sep 14 00:00:00 GMT+500 2019=[], Tue Sep 17 00:00:00 GMT+500 2019=[], Wed Sep 25 00:00:00 GMT+500 2019=[]}

It does sort the map in ascending order every time something's been put. Why is so? How to override it?

Another bypass it to create a copy of the current map and call Collections.reverse() but I don't want to do it because of the performance issues.

Thanks in advance.

Joe D
  • 44
  • 1
  • 10
  • 3
    Are you asking why a TreeMap sorts itself according to its Keys? Because that is literally the whole point of a TreeMap. If you want to keep the order of insertion you need to just use another type of map that is built for that (like LinkedHashMap) – OH GOD SPIDERS Sep 03 '19 at 09:21
  • 1
    "...but with the dates coming in descending order..." - note that your TreeMap uses the key's natural order which is ascending for dates. If you want the map to be sorted in descending order you'll need to provide an inverted "natural order" comparator, e.g. via `Comparator.naturalOrder().reversed()`. – Thomas Sep 03 '19 at 09:25
  • The `TreeMap` will sort your keys automatically regardless of insertion order as long as they implement `Comparable`. If you want to always sort them in descending order and don't want to override their behavior (with `Date`) or the elements are actually final (e.g. `String`s), you need to inject a `Comparator` while initializing your `Map`. You can also invoke `descendingMap` on it to generate a reverse-sorted map, which seems like the easiest solution here. – Mena Sep 03 '19 at 09:27
  • Yes, thank you very much, I know. How can I do that while initializing the map? – Joe D Sep 03 '19 at 09:41
  • @JoeD by using the correct [TreeMap](https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html) constructor. – Kayaman Sep 03 '19 at 09:55
  • Duplicate of - https://stackoverflow.com/questions/9338209/how-to-print-treemap-in-reverse-order – Aditya Sep 03 '19 at 11:46
  • @JoeD new TreeMap<>(Collections.reverseOrder()) – Serge Harnyk Sep 03 '19 at 11:47

1 Answers1

0

Thank you very much people I've changed the method to

public static <T> Map<T, List<String>> groupTimePeriods(List<DtObject> timePeriods, String groupProperty,Comparator treeMapComparator)
{
    Map<T, List<String>> groupedTimePeriods = new TreeMap<>((Comparator<? super T>) treeMapComparator);
}

As the last argument for descending order is Comparator.naturalOrder().reversed()

And now it's fine!

Joe D
  • 44
  • 1
  • 10