Comparing using
Comparators

Nicholas Duchon: Oct 4, 2015.

Outline


Newer

This is a code fragment using lambda expressions, responding to a JButton event:

I suggest looking at the following for more complete examples:

Note that if you know you are working with an ArrayList of Ship, for example, you can just do the following. The logic goes something like this:

Code

import javax.swing.JButton;
import java.util.ArrayList;
import java.util.Collections;

public class SortShipND {
  JButton jba = new JButton ();
  JButton jbb = new JButton ();
  ArrayList <Ship> als = new ArrayList <> ();

  {
    jba.addActionListener (e ->
        {Collections.sort (als, (a,b) ->
             a.m - b.m);});
    jbb.addActionListener (e -> {
         Collections.sort (als, (a,b) ->
             Double.compare (a.x, b.x));});
  } // instance initializer
} // end class SortShipND

class Ship {
  int m, n;
  double x, y, z;
} // end Ship


Original

The following is an excellent example of using Comparators to implement more than one way of comparing objects in a class. This code was developed by Branch Archer.

(Branch Archer) Therefore [context: a swindle involving areas and perimeters of rectangles], it is vitally important :-) that the Rectangle class have the ability to compare areas as well as perimeter, and I assume this is why this question is being asked. Of course, the most obvious way to do this is to name the methods compareArea and comparePerimeter. However, we might need to pass the comparator to some other function that needs to be able to select a comparison operation. Below I give an example of such a construct.

import java.util.*;

public class Rectangle {
int width, height;

// inner class definition:
public static Comparator areaComp = new Comparator() {
public int compare(Object a, Object b) {
return ( ((Rectangle)a).width * ((Rectangle)a).height ) - ( ((Rectangle)b).width * ((Rectangle)b).height );
} // end method compare
}; // area comparator


// inner class definition:
public static Comparator perimeterComp = new Comparator() {
public int compare(Object a, Object b) {
return ( ((Rectangle)a).width + ((Rectangle)a).height ) - ( ((Rectangle)b).width + ((Rectangle)b).height );
} // end method compare
}; // perimeter comparator


public Rectangle(int width, int height) {
this.width = width;
this.height = height;
} // end specific constructor

public int compareTo(Rectangle r, Comparator comp) {
return comp.compare(this, r);
} // end method compareTo

public static char comparisonOperator(int c) {
if ( c < 0 ) return '<';
if ( c > 0 ) return '>';
return '=';
} // end method comparisonOperator

public static void main(String[] args) {
Rectangle r1 = new Rectangle(10, 10);
Rectangle r2 = new Rectangle(5, 15);

char c = comparisonOperator(r1.compareTo(r2,Rectangle.perimeterComp));
System.out.println("Perimeter comparison: R1 " + c + " R2" );
c = comparisonOperator(r1.compareTo(r2,Rectangle.areaComp));
System.out.println("Area comparison: R1 " + c + " R2" );
} // end method main

} // end class Rectangle

Here I am comparing 10 × 10 rectangle R1 with 5 × 15 rectangle R2. The resulting output is

Perimeter comparison: R1 = R2
Area comparison: R1 > R2

In my example, I have implemented comparisonOperator for readability of the output, but the compareTo method is, of course, what is generally required. Prof. Duchon, is this what you were getting at? Branch Archer