2

I have a list List<Object[]>.

The Object[] has the following objects:

  • Date "dd.MM.yyyy"
  • String
  • Date "HH:mm".

I am able to sort the list after the dd.MM.yyyy and then after the String. Now I want to sort it after the time too also the result should be sorted "dd.MM.yyyy", sorted "String", sorted "time".

Collections.sort(resultList, new Comparator<Object[]>() {
    public int compare(Object[] o1, Object[] o2) {
        int dateComparison = (( o2[0]).compareTo(o1[0]));
        return dateComparison == 0 ? ( o1[1]).compareTo( o2[1]) : dateComparison;
    }
});

How can I get it to work?

GhostCat
  • 137,827
  • 25
  • 176
  • 248
benz
  • 693
  • 1
  • 9
  • 29
  • 6
    What is your actual problem? You need to add another comparison – Flown Jul 19 '17 at 09:20
  • Please elaborate or provide an example/use case. – Debanjan Jul 19 '17 at 09:22
  • 2
    How can you call `compareTo` if those are just Objects? – tobias_k Jul 19 '17 at 09:25
  • 3
    Don't use `Object[]`, especially like this. It looks like each Object array should be an instance of a class. Create a class Foo with three fields then make a `List`. You can then make your [`Foo` class implement Comparable](https://stackoverflow.com/questions/21626439/how-to-implement-the-java-comparable-interface) which allows you to call `Collections.sort` without specifying a Comparator. – Michael Jul 19 '17 at 09:26
  • 1
    @tobias_k Good spot. That, and the fact that there's weird superfluous brackets around the `o2[0]` and `o2[1]`, make me suspect they've edited out a cast. – Michael Jul 19 '17 at 09:31
  • Fyi: I updated my answer. Just in case you want to continue with your current approach - you now have some info how to easily do that. – GhostCat Jul 19 '17 at 12:05
  • Thanks for the quick accept :-) – GhostCat Jul 19 '17 at 16:25

3 Answers3

6

Your problem is: wrong abstraction.

When you have "data" that belongs together, then you turn that into a class.

Meaning: instead of keeping three lists with data, you create a class that reasonably "wraps" around these three pieces of information. And then you create an array/list of that class.

Because then you can easily create different Comparator objects that compare objects of that class - by looking at different fields for example.

In other words: your are (more or less) writing "procedural" code with flat data, and "outside" code that "combines" that flat data. But when using a OO language such as Java, you should instead strive to create helpful abstractions.

But in case you want to go on with your approach, have a look at this pseudo code:

int dateComparison = o2[0].compareTo(o1[0]);
if (dateComparison != 0) return dateComparison;

int stringComparison = o2[1].compareTo(o1[1]);
if (stringComparison != 0) return stringComparison;

int secondDateComparison = o2[2].compareTo(o1[2]);
return dateComparison;

( obviously you need some casts here and there, but as your input isn't using them I left that out as well )

GhostCat
  • 137,827
  • 25
  • 176
  • 248
3

Try this.

resultList.sort(
    Comparator.comparing((Object[] a) -> (Date)a[0])
        .thenComparing(a -> (String)a[1])
        .thenComparing(a -> (Date)a[2]));
  • Nice one. I am always surprised to see what interesting (and easy to digest!) solutions are possible using lambdas! – GhostCat Jul 19 '17 at 12:58
-1

Merge your Date and Time objects into a java.util.Date, then use your String as the key in a HashMap. From here, you can sort the List<HashMap<String, Date> by getting the Date first, then comparing the String keys using compareTo().

Just as a side note: if you are using a List of Arrays or a List of Lists, then it's likely a code smell.

Austin Schaefer
  • 695
  • 5
  • 19