Chapter 2. Using Built in Lambda Types
2.1. Describe the built in interfaces included in Java 8 - java.util.function package
New Package:
java.util.function
- Contains a lot of commonly used functional interfaces
java.util.function.Predicate
Represents a predicate (boolean-valued function) of one argument.
public interface Predicate<T extends Object> {
boolean test(T t);
}
java.util.function.Consumer
Represents an operation that accepts a single input argument and returns no result.
public interface Consumer<T extends Object> {
void accept(T t);
}
java.util.function.Function
Represents a function that accepts one argument and produces a result.
public interface Function<T extends Object, R extends Object> {
R apply(T t);
}
java.util.function.Supplier
Represents a supplier of results. There is no requirement that a new or distinct result be returned each time the supplier is invoked.
public interface Supplier<T extends Object> {
T get();
}
java.util.function.UnaryOperator
Represents an operation on a single operand that produces a result of the same type as its operand. This is a specialization of Function for the case where the operand and result are of the same type.
public interface UnaryOperator<T extends Object> extends Function<T, T> {
}
Know the above interfaces very well, the inputs as well as the output.
2.2. Develop code that uses Function interface
public interface Function<T extends Object, R extends Object> {
R apply(T t);
}
Example:
1
2
3
4
5
6
Function<String, Boolean> f = s -> new Boolean(s);
System.out.println(f.apply("TRUE"));
System.out.println(f.apply("true"));
System.out.println(f.apply("Java8"));
System.out.println(f.apply(null));
2.3. Develop code that uses Consumer interface
public interface Consumer<T extends Object> {
public void accept(T t);
}
Example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class ConsumerDemo {
static class Name {
String name;
Name(String nm) {
name = nm;
}
void setName(String nm) {
name = nm;
}
public String toString() {
return name;
}
}
public static void processList(List<Name> names, Consumer<Name> consumer) {
for (Name n : names) {
consumer.accept(n);
}
}
public static void main(String[] args) {
List<Name> list = Arrays.asList(new Name("a"), new Name("b"), new Name("c"), new Name("d"));
System.out.println(list);
Consumer<Name> capitalize = s -> s.setName(s.name.toUpperCase());
processList(list, capitalize);
System.out.println(list);
}
}
2.4. Develop code that uses Supplier interface
public interface Supplier<T extends Object> {
T get();
}
Example: Constructor reference (T::new)
- Much like a method reference, except it is a reference to a constructor instead of a method
- Constructor is not called just referenced.
- On get, the constructor will be called.
1
2
3
Supplier<String> sup = String::new;
System.out.println(sup); // com.jcp8.chapter.two.SupplierDemo$$Lambda$2/990368553@41629346
System.out.println(sup.get()); // ""
2.5. Develop code that uses UnaryOperator interface
public interface UnaryOperator<T extends Object> extends Function<T, T> {
}
Example:
1
2
UnaryOperator<String> uo = s -> "Have a " + s;
System.out.print(uo.apply("good one"));
2.6. Develop code that uses Predicate interface
public interface Predicate<T extends Object> {
boolean test(T t);
}
Example:
1
2
3
4
5
6
7
8
9
10
Predicate<String> boolTest = s -> new Boolean(s).booleanValue();
List<String> strList = Arrays.asList("TRUE", "true", null, "", "false", "TrUe");
processList(strList, boolTest);
private static void processList(List<String> list, Predicate<String> predicate) {
for (String s : list) {
System.out.println(s + " Test pass? " + predicate.test(s));
}
}
2.7. Develop the code that use primitive and binary variations of base interfaces of java.util.function package
A specialized version of the functional interfaces in order to avoid autoboxing operations when the inputs or outputs are primitives.
1
2
3
4
@FunctionalInterface
public interface IntPredicate {
boolean test(int i);
}
Mapping Table
You should know by just the Interface name, what parameter they accept and what they return.
How to remember
Intxx
-> Will take int as an argument and return T or nothing depending on type
ToIntxx
-> Will return int, and take in T as arg if it applies
Predicate<T> |
Consumer<T> |
Function<T, R> |
Supplier<T> |
UnaryOperator<T> |
---|---|---|---|---|
IntPredicate | IntConsumer | IntFunction |
IntSupplier | IntUnaryOperator |
LongPredicate | LongConsumer | LongFunction |
LongSupplier | LongUnaryOperator |
DoublePredicate | DoubleConsumer | DoubleFunction |
DoubleSupplier | DoubleUnaryOperator |
- | - | - | BooleanSupplier | - |
Additional Function<T, R>
IntToDoubleFunction
- Function that accepts an int-valued argument and produces a double-valued result.
IntToLongFunction
- Function that accepts an int-valued argument and produces a long-valued result.
LongToDoubleFunction
- Function that accepts a long-valued argument and produces a double-valued result.
LongToIntFunction
- Function that accepts a long-valued argument and produces an int-valued result.
ToIntFunction<T>
- Function that produces an int-valued result.
ToDoubleFunction<T>
- Function that produces a double-valued result.
ToLongFunction<T>
- Function that produces a long-valued result.
Binary Interfaces - Takes two inputs instead of one
Predicate<T> |
Consumer<T> |
Function<T, R> |
Supplier<T> |
UnaryOperator<T> |
|
---|---|---|---|---|---|
Type | BiPredicate<L, R> | BiConsumer<T, U> | BiFunction<T, U, R> | - | BinaryOperator |
Params | (L, R) -> boolean | (T, U) -> void | (T, U) -> R | - | (T, T) -> T |
Additional Ones
Binary Operators
IntBinaryOperator
- Function operation upon two int-valued operands and producing an int-valued result.
LongBinaryOperator
- Function operation upon two long-valued operands and producing a long-valued result.
DoubleBinaryOperator
- Function operation upon two double-valued operands and producing a double-valued result.
Object Consumers
ObjIntConsumer<T>
- Function operation that accepts an Object-valued and an int-valued argument and returns no result.
ObjLongConsumer<T>
- Function operation that accepts an Object-valued and a long-valued argument and returns no result.
ObjDoubleConsumer<T>
- Function operation that accepts an Object-valued and a double-valued argument and returns no result.
To Primitive Bi-Functions
ToIntBiFunction<T, U>
- Function that accepts two arguments and produces an int-valued result.
ToLongBiFunction<T, U>
- Function that accepts two arguments and produces a long-valued result.
ToDoubleBiFunction<T, U>
- Function that accepts two arguments and produces a double-valued result.
You have to know each of the above types for the exam, with their arguments and return types.
2.8. Develop the code that use method reference; including refactor the code that use Lambda expression to use method references
Method References
- shorthand for lambdas calling only a specific method
- the target reference is placed before the delimiter :: and the name of the method is provided after it.
- String::toUpperCase is a method reference to the method toUpperCase defined in the String class, shorthand for the lambda expression (String s) -> s.toUpperCase();
Four Types:
ContainingClass::staticMethodName - Reference to a static method ContainingObject::instanceMethodName - Reference to an instance method of a particular object ContainingType::methodName - Reference to an instance method of an arbitrary object of a particular type ClassName::new - Reference to a constructor
Reference to a static method - Class::staticMethodName
IntFunction<String> f1 = (i) -> String.valueOf(i);
System.out.println(f1.apply(100));
IntFunction<String> f1 = String::valueOf;
System.out.println(f1.apply(100));
Reference to a constructor - ClassName::new
Function<char[], String> f1 = String::new;
System.out.println(f1.apply(new char[] {'H', 'i'}));
Reference to an instance method of an arbitrary object of a particular type - Class::instanceMethodName
Reference to an instance method of an arbitrary object of a particular type refers to a non-static method that is not bound to a receiver.
String::trim // (String str) -> { return str.trim(); }.
BiFunction<String, String, Boolean> f1 = String::equalsIgnoreCase;
System.out.println(f1.apply("Hello", "HELLO"))
Reference to an instance method of a particular object - Object::instanceMethodName
Reference to an instance method of a particular object refers to a non-static method that is bound to a receiver.
This kind of method references refers to a situation when you are calling a method in a lambda to an external object that already exists
Integer i = new Integer(1);
Supplier<String> f1 = i::toString;
System.out.println(f1.get());
Know when to use which type of method reference.
Next Chapter - Filtering Collections with Lambdas