Sort List in place by a variable deep down in the structure in a complex Object

Viewed 40

I have a complex "Order" object parsed from json. Somewhere deep in the structure i have the orderDate. I can extract it only as a STRING! And now I try to sort a List of Orders in place.

I came with the Idea of creating a new List, where the array inside consist two elements, first the Order Object itself, second the Date parsed to A Date object. eg. new Object[]{order, new Date(order.getOrderDate())}. Then sort by second element and then parse back to a List and return. But this creates two new Lists and is not in place.

The other idea is to create a custom Comparator that sorts like this

    orders.sort(new Comparator<Order>() {
        @Override
        public int compare(Order o1, Order o2) {
            return new Date(o1.getOrderDate()).compareTo(new Date(o2.getOrderDate()));
        }
    });

But the second variant will create a lot of new Date Objects. Worst case a lot times for every entry.

Is there a more beautiful way around it?

2 Answers

It's possible to create Date instance for unique date - using Map.

final Comparator<Order> sortByDateAsc = new Comparator<Order>() {
    private final Map<String, Date> map = new HashMap<>();

    @Override
    public int compare(Order o1, Order o2) {
        Date d1 = map.computeIfAbsent(o1.getOrderDate(), Date::new);
        Date d2 = map.computeIfAbsent(o2.getOrderDate(), Date::new);
        return d1.compareTo(d2);
    }
};

orders.sort(sortByDateAsc);

The only option in the scenario you provided is to compare the Strings directly. So basically splitting the strings down to there respective content (year, month, day, ...) and then compare those values. You could return as soon as one valule is higher, e.g. if a.month > b.month, you would not have to compare day etc.

But on the other hand, that's probably uglier and also not necessarily more performant than your current approach.

A much better approach is to adjust your JSON parsing. A JSON should always be parsed into its respective counterpart, instead of keeping the strings. So adjust your parsing to already have Date instead of String and save yourself the hassle of having to work with the data later on in your code. That is what marshalling is supposed to do, leave you with a plain (e.g.) Java representation of the JSON to work with it without having to bother with its origins.

Related