Is it possible to implement reverseOrder () method with Comparator <T>?

I have analyzed the Comparator interface in Java SE 8. Now I am interested in how to use a method reverseOrder()

using a class that implements the interface Comparator<T>

. I wrote a sample program to test this.

class NaturalOrderString implements Comparator<String>{
    @Override
    public int compare(String o1, String o2) {
        // TODO Auto-generated method stub
        return o1.compareTo(o2);
    }               
} 

public class App {
  public static void main(String[] args) { 
      Comparator<String> mycom= new NaturalOrderString();

      mycom.reverseOrder(); // can't use this
   }
}

      

So now I have to use all methods related to the interface Comparator

. But surprisingly the serum I am typing mycom.

, then there is no suggestion for the reverseOrder () method. What for? The class NaturalOrderString

implements Comparator<T>

.

So, I have to accept an object mycom

to access the method reverseOrder()

. Is not it?

Also, I found out that sorting in lists happens with natural ordering . Therefore, using the Collection class , I could access the method reverseOrder()

. So, before my example, I could happily write

Collections.reverseOrder(mycom); // that fine.

      

But my question is, why can't I use reverseOrder()

using an object of the class that implements Comparator<T>

? And since we can't access it, why does Java include the method reverseOrder()

in the interface Comparator<T>

?

Or, if it is indeed possible to access reverseOrder()

through the mycom object regarding my code, please provide an example.

+3


source to share


5 answers


Basically, the reverseOrder () method returns a comparator that imposes the reverse on the natural ordering.

First, following your question, since reverseOrder () is , you cannot use it like mycom.reverseOrder (). You must use both Comparot.reverseOrder (). Following your code. I created an ArrayList to demonstrate and use Comparator.reverseOrder () static method



public class App {

public static void main(String[] args) {
    // TODO Auto-generated method stub

    List<String> people= new ArrayList<String>();
    people.add("Sam");
    people.add("Bob");
    people.add("Andrew");
    people.add("Michel");
    people.add("Abe");
    people.add("John");

    Comparator<String> mycom= new NaturalOrderString();

    Collections.sort(people); // this will sort the people array list in natural order

    Collections.sort(people,Comparator.reverseOrder()); // Here your desired method it will reverse the natural order as documentation.

     }
  }

      

Hope you now understand this concept.

+1


source


In principle, a lot of magic is possible here.

To undo the sort, you just need to "undo" the comparison result.

You can examine these foils . They are written in German, but there is not much text there and the code is all java. The presentation introduces some of the basics of lambda; then explain how you can use lambdas and method references to design an entire system where you sort / reverse sort streams; using "accessor" objects to retrieve any properties from things you are about to sort.



For example, leading to:

interface Comparator<T> {
  public int compare(T a, T b);
  public default Comparator<T> reversed() {
    return (a, b) –> compare(b, a) ;
}

      

Now you can implement this interface, and reverse sorting comes free.

+3


source


The method Comparator.reverseOrder()

just delegates Collections.reverseOrder()

and Collections.reverseOrder()

just returns a comparator that implements the reverse natural ordering.

What you are trying to do is as simple as:

@Override
public int compare(String o1, String o2) 
{
    int d = o1.compareTo(o2);
    return -d;

      

which can also be achieved with myComparator.reversed()

.

+1


source


Because it Comparator.reverseOrder

is a static method.

From the JLS :

[8.4.8] The class does not inherit static methods from its superinterfaces.

If you want to use this method, you can simply call it Comparator.reverseOrder()

. However, this doesn't seem to be what you actually want - use non-static instead reversed()

.

0


source


Can Comparator.reverseOrder () be used

Yes, of course you can. It's just not immediately obvious how you can use it, because the compiler conveys a lot of information.

Signature:

static <T extends Comparable<? super T>> Comparator<T> reverseOrder()

      

So, as you can see, a generic type is required that must implement Comparable

. It is somewhat stricter than that: it requires the type to be comparable to itself or to one of its supertypes. We were unable to obtain an inverse comparator for Apple using the following definitions:

public class Orange { }
public class Apple implements Comparable<Orange> { /* methods */ }

      

reverseOrder

takes no arguments, but returns us the Comparator

type we are passing. You can use it like this:

Comparator<Foo> reverseCompatator = Comparator.<Foo>reverseOrder();

      

Here's a complete, compiled example:

// Simply wraps an integer value
class Foo implements Comparable<Foo>
{
    private final Integer value;

    Foo(final Integer value) {
        this.value = value;
    }

    public int compareTo(Foo that) {
        // use standard integer comparison (i.e. 1,2,3,4,5,...)
        return this.value.compareTo(that.value);
    }

    @Override
    public String toString() {
        return "Foo " + value;
    }
}

public class Main
{
    public static void main (String[] args)
    {
        // create a list
        List<Foo> foos = Arrays.asList(new Foo(1), new Foo(3), new Foo(5));

        // sort the list in reverse
        foos.sort(
            Comparator.<Foo>reverseOrder()
        );

        System.out.println(foos);
    }
}

      

Output example:

[Foo 5, Foo 3, Foo 1]

In practice, you can remove <Foo>

from Comparator.<Foo>

, because the compiler might decide what you need.

0


source







All Articles