Creating Comparator Objects
Functional Interfaces A functional interface is an interface that requires exactly one method.
Lambdas
These are anonymous functions. They have various guises.
Quickies Here is a lambda that squares. In this form the right-hand side is evaluated and it is returned.
x -> x*x
Here is a Quickie that adds.
(x, y) -> x + y
Note the need for parentheses when there are two or more arguments.
This is an argless quickie lambda.
() -> System.out.println("foo");
What if you have several lines of code? Contain the code in curly braces. However, if you do this, you must have an explicit return statement.
(a, b) ->
{
if(a.x == b.x)
{
return a.y - b.y;
}
return a.x - b.x;
}
Can I restrict the types that are passed in? Yes. Like so.
(OrderedPair a, OrderedPair b) ->
{
if(a.x == b.x)
{
return a.y - b.y;
}
return a.x - b.x;
}
This lambda will only accept objects of
OrderedPair
type.
This is possible in quickie lambdas too.
(double x) -> x*x
Implementing Comparable
Firstly, if you are going to create sortabe objects, it is a smart idea
to have them implement the Comparable<T>
, an
interface specifies one method, compareTo
.
public class OrderedPair implements Comparable<OrderedPair>
{
private final int x;
private final int y;
public OrderedPair(int x, int y)
{
this.x = x;
this.y = y;
}
public int compareTo(OrderedPair q)
{
if(x == q.x)
{
return y - q.y;
}
return x - q.x;
}
@Override
public String toString()
{
return String.format("(%s, %s)", x, y);
}
public static void main(String[] args)
{
}
}
The compareTo
method works like this.
If, metaphorically, x < y
, then
x.compareTo(y) < 0
. This method
will compare the ordered pairs in "dictionary" order.
It will first compare the x-coördinates of the two
ordered pairs; if they are equal, it will then compare
the y-coördinates.
A big advantage to doing this lies in the static method
sort
in the class
java.util.Collections
. This method will
use compareTo
to sort a list of
OrderedPairs
. Here we make it happen.
import java.util.ArrayList;
import java.util.Collections;
public class OrderedPair implements Comparable<OrderedPair>
{
private final int x;
private final int y;
public OrderedPair(int x, int y)
{
this.x = x;
this.y = y;
}
public int compareTo(OrderedPair q)
{
if(x == q.x)
{
return y - q.y;
}
return x - q.x;
}
@Override
public String toString()
{
return String.format("(%s, %s)", x, y);
}
public static void main(String[] args)
{
ArrayList<OrderedPair> pairs = new ArrayList<>();
pairs.add(new OrderedPair(1,2));
pairs.add(new OrderedPair(2,1));
pairs.add(new OrderedPair(4,5));
pairs.add(new OrderedPair(5,3));
pairs.add(new OrderedPair(3,4));
pairs.add(new OrderedPair(3,5));
pairs.add(new OrderedPair(3,0));
pairs.add(new OrderedPair(3,6));
pairs.add(new OrderedPair(1, -3));
pairs.add(new OrderedPair(6, 2));
pairs.add(new OrderedPair(7, -1));
System.out.println(pairs);
Collections.sort(pairs);
System.out.println(pairs);
}
}
Compile and run.
$ javac OrderedPair.java $ java OrderedPair [(1, 2), (2, 1), (4, 5), (5, 3), (3, 4), (3, 5), (3, 0), (3, 6), (1, -3), (6, 2), (7, -1)] [(1, -3), (1, 2), (2, 1), (3, 0), (3, 4), (3, 5), (3, 6), (4, 5), (5, 3), (6, 2), (7, -1)]
The Collections.sort
method sorts our
pairs in dictionary order.
The compareTo
method is refererred to in the
documentation as the natural ordering.
Creating a Custom Sort with a Comparator
We are going to use lambdas to do this. Here is the code.
Comparator<OrderedPair> yFirst = (a, b) ->
{
if(a.y == b.y)
{
return a.x - b.x;
}
return a.y - b.y;
};
What is happening here?
Comparator<T>
is an interface specifying one
method, compare(T x, T y)
.
This interface is functional.
So Java creates an object that is an instance of
an nameless class that implements Comparator<T>
and has the lambda as its method compare(T x, T y)
.
We will pass this as the second argument to Collections.sort()
and the pairs will be sorted by their y-value first then their x-value.
Note, in the code below, that you need an additional import.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class OrderedPair implements Comparable<OrderedPair>
{
private final int x;
private final int y;
public OrderedPair(int x, int y)
{
this.x = x;
this.y = y;
}
public int compareTo(OrderedPair q)
{
if(x == q.x)
{
return y - q.y;
}
return x - q.x;
}
@Override
public String toString()
{
return String.format("(%s, %s)", x, y);
}
public static void main(String[] args)
{
ArrayList<OrderedPair> pairs = new ArrayList<>();
pairs.add(new OrderedPair(1,2));
pairs.add(new OrderedPair(2,1));
pairs.add(new OrderedPair(4,5));
pairs.add(new OrderedPair(5,3));
pairs.add(new OrderedPair(3,4));
pairs.add(new OrderedPair(3,5));
pairs.add(new OrderedPair(3,0));
pairs.add(new OrderedPair(3,6));
pairs.add(new OrderedPair(1, -3));
pairs.add(new OrderedPair(6, 2));
pairs.add(new OrderedPair(7, -1));
System.out.println(pairs);
Collections.sort(pairs);
System.out.println(pairs);
Comparator<OrderedPair> yFirst = (a, b) ->
{
if(a.y == b.y)
{
return a.x - b.x;
}
return a.y - b.y;
};
Collections.sort(pairs);
System.out.println(pairs);
}
}
Run and Compile.
$ !javac javac OrderedPair.java $ java OrderedPair [(1, 2), (2, 1), (4, 5), (5, 3), (3, 4), (3, 5), (3, 0), (3, 6), (1, -3), (6, 2), (7, -1)] [(1, -3), (1, 2), (2, 1), (3, 0), (3, 4), (3, 5), (3, 6), (4, 5), (5, 3), (6, 2), (7, -1)] [(1, -3), (1, 2), (2, 1), (3, 0), (3, 4), (3, 5), (3, 6), (4, 5), (5, 3), (6, 2), (7, -1)]
FileIO and Exceptions
The Throwable Subtree
------------------- | Object | ------------------- | | ------------------- | Throwable | ------------------- / \ / \ -------------- ------------ | Error | |Exception | -------------- ------------ | Inevitable -------------------- Death! | RuntimeException | -------------------- Largely programmer goofs: IllegalArgumentException ArithmeticException IndexOutOfBoundsException
It is optional to guard against runtime exceptions. All other exceptions must be handled by the try-catch-throw-finally mechanism.