JetBrains Academy: Standard functional interfaces - Kamil-Jankowski/Learning-JAVA GitHub Wiki
Accounts:
You have a class Account(String number, Long balance, boolean isLocked)
, the list accounts of type List<Account>
and the method filter(List<T> elems, Predicate<T> predicate)
for filtering the given list of type T by the predicate.
The class Account
has the next methods: getNumber()
, getBalance()
, isLocked()
for getting the values of the corresponding fields.
Write code for filtering the accounts list in two ways:
- get list with all non-empty accounts (balance > 0) and save it to the variable
nonEmptyAccounts
-
get all non-locked accounts with too much money (balance >= 100 000 000) and save it to the variable
accountsWithTooMuchMoney
The classAccount
, the listaccounts (List<Account>)
and the methodfilter(...)
will be available during testing.
Example of use the filter method: The code below gets only even number from the list.
List<Integer> numbers = ...
List<Integer> evenNumbers = filter(numbers, number -> number % 2 == 0);
PS: it's often called behaviour parametrization because behaviour of the method filter
is dependent of the given predicate.
List<Account> nonEmptyAccounts = filter(accounts, acc -> acc.getBalance() > 0);
List<Account> accountsWithTooMuchMoney = filter(accounts, acc -> !acc.isLocked() && acc.getBalance() >= 100000000);
Ternary operator:
Let's combine function to build more complex functions using standard functional interfaces.
Given the predicate condition
and two functions ifTrue
and ifFalse
. Implement a method ternaryOperator
which builds a new function returning the result of invoking ifTrue
, if the predicate is true and otherwise - the result of invoking ifFalse
.
Here is an example:
Predicate<Object> condition = Objects::isNull;
Function<Object, Integer> ifTrue = obj -> 0;
Function<CharSequence, Integer> ifFalse = CharSequence::length;
Function<String, Integer> safeStringLength = ternaryOperator(condition, ifTrue, ifFalse);
In the example above, the resulting function returns the length of a string if the reference to the string is not null, otherwise, it returns 0.
Note: it can be collapsed into a single line, but for clarity, additional variables are used.
public static <T, U> Function<T, U> ternaryOperator(
Predicate<? super T> condition,
Function<? super T, ? extends U> ifTrue,
Function<? super T, ? extends U> ifFalse) {
return x -> condition.test(x) ? (U) ifTrue.apply(x) : (U) ifFalse.apply(x);
}
An infinite numbers supplier:
Create a supplier that return integer values from 0 to infinity.
After first get()
invocation supplier must return 0. After second - 1, next - 2, 3 etc.
Supplier<Integer> sup = getInfiniteRange();
for(int i = 0; i < 5; i++) {
System.out.print(sup.get() + " ");
}
So this code should print "0 1 2 3 4 ".
Also it should be possible to use separate suppliers simultaneously.
Supplier<Integer> sup1 = getInfiniteRange();
Supplier<Integer> sup2 = getInfiniteRange();
for(int i = 0; i < 5; i++) {
System.out.print(sup1.get() + " " + sup2.get() + " ");
}
For example, this code should print "0 0 1 1 2 2 3 3 4 4 ".
import java.util.function.*;
class FunctionUtils {
public static Supplier<Integer> getInfiniteRange() {
Integer[] numbers = {0};
return () -> numbers[0]++;
// or:
// return IntStream.iterate(0, i -> i + 1).iterator()::next;
}
}