Slide navigation: Forward with space bar, → arrow key, or PgDn. Backwards with ← or PgUp.

Copyright © Cay S. Horstmann 2016
Arrays.sort sorts an array if the element class conforms to the Comparable interface.public interface Comparable<T> {
int compareTo(T other); // automatically public
}compareTo method.public class Employee implements Comparable<Employee> {
public int compareTo(Employee other) {
return Double.compare(salary, other.salary);
}
...
}
Employee objects:
Employee[] staff = ...; Arrays.sort(staff);
if (a[i].compareTo(a[j]) > 0) {
// rearrange a[i] and a[j]
...
}
a[i].compareTo(a[j]) is valid?a[i] is an instance of Comparable, then a[i] has a compareTo method:
public static <T extends Comparable<? super T>> void sort(T[] a)
Add logging to show invocation
Collection/Collections, Path/PathsPaths class has a factory method get to make a Path object.Path interface:
public interface Path {
public static Path get(String first, String... more) {
return FileSystems.getDefault().getPath(first, more);
}
...
}public interface Comparable<T> {
default int compareTo(T other) { return 0; }
// By default, all elements are the same
}
public interface MouseListener {
default void mouseClicked(MouseEvent event) {}
default void mousePressed(MouseEvent event) {}
...
}
public interface Collection {
int size(); // An abstract method
default boolean isEmpty() { return size() == 0; }
...
}Collection interface that has been in the JDK for many years.Bag implementing Collection.Collection. (This actually happened with the stream method in JDK 8.)Bag no longer compiles—the change is not source compatible.Bag class still works, as long as nobody calls the new method. (Otherwise, an AbstractMethodError occurs.)default method solves both problems.interface Person { default String getName() { ... }}
interface Named { default String getName() { ... }}
class Employee implements Person, Named {
public String getName() { return Person.super.getName(); }
...
}
class Employee { public String getName() { ... } ... }
class Manager extends Employee implements Named { ... }Named.getName is ignored.Arrays.sort sorts an array of Comparable objects.
Comparable?Arrays.sort accepts a comparator callback:
public interface Comparator<T> {
int compare(T first, T second);
}class LengthComparator implements Comparator<String> {
public int compare(String first, String second) {
return first.length() - second.length();
}
}Arrays.sort:
String[] friends = { "Peter", "Paul", "Mary" };
Arrays.sort(friends, new LengthComparator());
class NameComparator implements Comparator<Employee> {
public int compare(Employee first, Employee second) {
return first.getName().compareTo(second.getName());
}
}

private and private static methods.default, static, private, or private staticdefault and static methods of the same interface.compare method had to be called repeatedly to compute:
first.length() - second.length()
(String first, String second) -> first.length() - second.length()
class LengthComparator implements Comparator<String> {
public int compare(String first, String second) {
return first.length() - second.length();
}
}
(parameters) -> expression{ } and a return statement:
(String first, String second) -> {
if (first.length() < second.length()) return -1;
else if (first.length() > second.length()) return 1;
else return 0;
}() -> System.out.println(Instant.now());
Comparator<String> comp = (first, second) -> first.length() - second.length();
ActionListener listener = event -> System.out.println(event);
Runnable, ActionListener, ComparatorArrays.sort(words,
(first, second) -> first.length() - second.length());
Timer t = new Timer(1000, event -> {
System.out.println("At the tone, the time is " + Instant.now());
});
(e1, e2) -> e1.getName().compareTo(e2.getName())java.util.function package defines generic functional interfaces:
public interface Predicate<T> {
boolean test(T t);
...
}
public interface BiFunction<T, U, R> {
R apply(T t, U u);
}
ArrayList has a removeIf method that takes a predicate:
list.removeIf(e -> e == null);
Timer t = new Timer(1000, event -> System.out.println(event));
Timer t = new Timer(1000, System.out::println);
Arrays.sort(words, String::compareToIgnoreCase)
object::instanceMethodClass::staticMethodClass::instanceMethodPerson::new is a reference to a Person constructor.
s -> new Person(s)Person objects:
ArrayList<String> names = . . .;
Stream<Person> stream = names.stream().map(Person::new);map method turns a stream of strings into a stream of Person objects.int[]::new is the same as the lambda expression n -> new int[n]new T[n]Person[] people = stream.toArray(Person[]::new);
public static void repeatMessage(String text, int delay) {
ActionListener listener = event -> {
System.out.println(text);
};
new Timer(delay, listener).start();
}
repeatMessage("Hello", 1000); // Prints Hello every 1,000 milliseconds
text variable is not defined in the lambda expression. repeatMessage returns!public static void countDown(int start, int delay) {
ActionListener listener = event -> {
start--; // Error: Can't mutate captured variable
System.out.println(start);
};
new Timer(delay, listener).start();
}public static void repeat(String text, int count) {
for (int i = 1; i <= count; i++) {
ActionListener listener = event ->
System.out.println(i + ": " + text); // Error: Cannot refer to changing i
new Timer(1000, listener).start();
}
}n times:
repeat(10, () -> System.out.println("Hello, World!"));
public static void repeat(int n, Runnable action) {
for (int i = 0; i < n; i++) action.run();
}
java.util.function package:
public static void repeat(int n, IntConsumer action) {
for (int i = 0; i < n; i++) action.accept(i);
}repeat(10, i -> System.out.println("Countdown: " + (9 - i)));Comparator interface has useful methods for creating and composing comparators.comparing makes a comparator from a key extractor function:
Arrays.sort(people, Comparator.comparing(Employee::getName));
comparingInt or comparingDouble to avoid boxing:
Arrays.sort(words, Comparator.comparingInt(String::length));
thenComparing chains comparators:
Arrays.sort(people,
Comparator.comparingDouble(Employee::getSalary)
.thenComparing(Employee::getName));
Comparator.comparingDouble(Employee::getSalary)
.thenComparing(Employee::getName));