박두준
박두준

Reputation: 167

How to convert Comparator to compare?

Here's the code that I'm trying to get.

public static final Comparator<Youku> AscDurRevCreationDate =
      Comparator.comparing(Youku::getDuration)
          .reversed()
          .thenComparing(Youku::getDateCreation)
          .reversed();

And the code below is the one I'm trying to convert it to. However, I'm getting a little different result from this code below. Btw, I'm using the Duration object in here.

@Override
  public int compare(Youku obj1, Youku obj2) {
    Integer duration = obj1.getDuration().compareTo(obj2.getDuration());
    Integer dateCreation = obj2.getDateCreation().compareTo(obj1.getDateCreation());

    return duration.compareTo(dateCreation );
  }

Upvotes: 1

Views: 229

Answers (2)

WJS
WJS

Reputation: 40062

Looking at your original requirement I feel compelled to point out that specifying reversed() reverses the desired order of all the previously specified sorting orders. So assuming a default ascending sorting order for all, the following:

public static final Comparator<Youku> comparator =
    Comparator.comparing(Youku::getDuration)
      .reversed()
      .thenComparing(Youku::getDateCreation)
      .reversed();

Sorts first in ascending order of duration and then in descending order of creation since the second reversed() reverses the previous orders. So to sort both in descending, remove the first reversed().

Say you wanted to sort by duration in ascending order but by creation in descending order. Then you could do it this way.

public static final Comparator<Youku> comparator =
    Comparator.comparing(Youku::getDuration)
      .thenComparing(Youku::getDateCreation, Comparator.reversedOrder());

The Comparator.reverseOrder() only affects the current mode of sorting.

If you want to see an easy example of this, check out the following. You can adjust the comparator to see the different results.

int[][] vals = { { 30, 6 }, { 40, 7 }, { 40, 8 }, { 10, 1 },
        { 10, 2 }, { 20, 3 }, { 20, 4 }, { 30, 5 }, { 50, 9 },
        { 50, 10 }, { 60, 11 }, { 60, 12 } };


// ascending first, descending second
Comparator<int[]> comp =
        Comparator.comparing((int[] a) -> a[0])
                .reversed()
        .thenComparing(a -> a[1])
                .reversed();

Arrays.sort(vals,comp);
for(int[] v : vals) {
    System.out.println(Arrays.toString(v));
}

Prints

[10, 2]
[10, 1]
[20, 4]
[20, 3]
[30, 6]
[30, 5]
[40, 8]
[40, 7]
[50, 10]
[50, 9]
[60, 12]
[60, 11]

Upvotes: 1

Zabuzard
Zabuzard

Reputation: 25903

Explanation

Looking at your Comparator:

public static final Comparator<Youku> AscDurRevCreationDate =
      Comparator.comparing(Youku::getDuration)
          .reversed()
          .thenComparing(Youku::getDateCreation)
          .reversed();

You want to compare Youkus by their duration (getDuration), descending and not ascending (reversed()) and if two durations are equal, break the ties by the creation date (getDateCreation), descending.

The correct Comparable implementation for that looks like:

@Override
public int compareTo(Youku other) {
    int durationResult = Integer.compare(getDuration(), other.getDuration());
    durationResult *= -1; // for reversed

    if (durationResult != 0) { // different durations
        return durationResult;
    }

    // break ties using creation date
    int creationDateResult = Integer.compare(getDateCreation(), other.getDateCreation());
    creationDateResult *= -1;

    return creationDateResult;
}

or in compact:

int durationResult = -1 * Integer.compare(getDuration(), other.getDuration());
return durationResult != 0
    ? durationResult
    : -1 * Integer.compare(getDateCreation(), other.getDateCreation());

Based on Comparator

Alternatively you can also implement the method based on the Comparator you already have:

public static final Comparator<Youku> comparator =
    Comparator.comparing(Youku::getDuration)
      .reversed()
      .thenComparing(Youku::getDateCreation)
      .reversed();

...

@Override
public int compareTo(Youku other) {
   return comparator.compare(this, other);
}

Notes

Your code attempt does not show a Comparable implementation but a manual implementation for a Comparator. I suppose you confused something there.

Upvotes: 5

Related Questions