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
/Paths
Paths
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 static
default
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
, Comparator
Arrays.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::instanceMethod
Class::staticMethod
Class::instanceMethod
Person::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));