Lambda Expressions: Reducing Java Lambda Expressions
What we’ll cover:
- How do I express a less complex lambda as a more complex lambda?
- Function as BiFunction
- BiConsumer as BiFunction
- Consumer as BiConsumer
- Predicate as Function
- Supplier as Function
- Runnable as Supplier
Functional Interfaces
| Name | Has Return-Value | Takes Argument 1 | Takes Argument 2 | |————|———|——————|——————| | Runnable | No | No | No | | Supplier | Yes | No | No | | Consumer | No | Yes | No | | BiConsumer | No | Yes | Yes | | Function | Yes | Yes | No | | BiFunction | Yes | Yes | Yes |
Functional Interfaces
- A
Runnableis no-argument, void-returning. - A
Functionis single-argument, non-void-returning. - A
Predicateis single-argument, boolean-returning. - A
Consumeris single-argument, void-returning. - A
Supplieris no-argument, non-void-returning. - A
BiConsumeris two-argument, void-returning. - A
BiFunctionis two-argument, non-void-returning.
Function as BiFunction
- Given a function
Function<Integer, String>, one can express a functionally equivalentBiFunction<Integer, Object, String>.- By omitting the second argument of the
BiFunction, we acquire a single-argument method
- By omitting the second argument of the
public void demo() {
Function<Integer, String> function
= (intVal) -> intVal.toString();
BiFunction<Integer, Object, String> biFunction
= (intVal, obj) -> intVal.toString();
}
Function as BiFunction
- Given a function
Function<Integer, String>, one can express a functionally equivalentBiFunction<Integer, Object, String>.- By encapsulating the
functioncall in thebiFunctiondefinition, we acquire identical behavior
- By encapsulating the
public void demo() {
Function<Integer, String> function
= (intVal) -> intVal.toString();
BiFunction<Integer, Object, String> biFunction
= (intVal, obj) -> function.apply(intVal);
}
BiConsumer as BiFunction
- Given a biconsumer
BiConsumer<Integer, String>, one can express a functionally equivalentBiFunction<Integer, Object, String>.- By ignoring the return-value of the
biFunction, we acquire a two-argument void-returning operation
- By ignoring the return-value of the
public void demo() {
BiConsumer<Integer, String> consumer = (intVal, stringVal) ->
System.out.println(intVal + stringVal);
BiFunction<Integer, String, Object> biFunction = (intVal, stringVal) -> {
System.out.println(intVal + stringVal);
return null;
};
}
BiConsumer as BiFunction
- Given a biconsumer
BiConsumer<Integer, String>, one can express a functionally equivalentBiFunction<Integer, Object, String>.
public void demo() {
BiConsumer<Integer, String> consumer = (intVal, stringVal) ->
System.out.println(intVal + stringVal);
BiFunction<Integer, String, Object> biFunction = (intVal, stringVal) -> {
consumer.accept(intVal, stringVal);
return null;
};
}
Consumer as BiConsumer
- Given a consumer
Consumer<String>, one can express a functionally equivalentBiConsumer<String, Object>
public void demo() {
Consumer<String> consumer = (name) -> System.out.println("Hello " + name);
BiConsumer<String, Object> = (name, obj) -> System.out.println("Hello " + name);
}
Consumer as BiConsumer
- Given a consumer
Consumer<String>, one can express a functionally equivalentBiConsumer<String, Object>
public void demo() {
Consumer<String> consumer = (name) -> System.out.println("Hello " + name);
BiConsumer<String, Object> = (name, obj) -> consumer.accept(name);
}
Predicate as Function
- Given a predicate
Predicate<String>one can express a functionally equivalentFunction<String, Boolean>
public void demo() {
Predicate<String> predicate = (string) ->
string.startsWith("A");
Function<String, Boolean> function = (string) ->
string.startsWith("A");
}
Predicate as Function
- Given a predicate
Predicate<String>one can express a functionally equivalentFunction<String, Boolean>
public void demo() {
Predicate<String> predicate = (string) ->
string.startsWith("A");
Function<String, Boolean> function = (string) ->
predicate.test(string);
}
Supplier as Function
- Given a supplier,
Supplier<String>one can express a functionally equivalentSupplier<Object, String>
public void demo() {
Supplier<String> supplier = () ->
String.valueOf(System.currentTimeMillis());
Function<String, Boolean> function = (obj) ->
String.valueOf(System.currentTimeMillis());
}
Supplier as Function
- Given a supplier,
Supplier<String>one can express a functionally equivalentFunction<Object, String>
public void demo() {
Supplier<String> supplier = () ->
String.valueOf(System.currentTimeMillis());
Function<String, Boolean> function = (obj) ->
supplier.get();
}
Runnable as Supplier
- Given a runnable,
Runnableone can express a functionally equivalentSupplier<Object>public void demo() { Runnable runnable = () -> System.out.println("Hello world!"); Supplier<Object> supplier = () -> { System.out.println("Hello world!"); return null; }; }