Primitive Type Specializations of Function<T, R>
As can be seen in Table 13.7, there are three categories of primitive type one-arity specializations of the Function<T, R> interface, each distinguished by a naming scheme. Also, these primitive type one-arity specializations do not define any default methods.
- PrimFunction<R>, where Prim is either Int, Long, or Double
These one-arity generic functions have the functional method apply: primitive -> R, where primitive is an int, long, or double—the function takes an argument of primitive type and returns a result of type R.
IntFunction<String> intToStr = i -> Integer.toString(i);
System.out.println(intToStr.apply(2021)); // “2021”
- ToPrimFunction<T>, where Prim is either Int, Long, or Double
These one-arity generic functions have the functional method applyAsPrim: T-> primitive, where primitive is an int, long, or double—the function takes an argument of type T and returns a result of primitive type.
ToIntFunction<String> strToInt = str -> Integer.parseInt(str);
System.out.println(strToInt.applyAsInt(“2021”)); // 2021
- Prim1ToPrim2Function, where Prim1 and Prim2 are Int, Long, or Double, and Prim1 != Prim2
These one-arity non-generic functions have the functional method applyAsPrim2: primitive1 -> primitive2, where primitive1 and primitive2 are int, long, or double, and primitive1 != primitive2—the function takes an argument of type primitive1 and returns a result of type primitive2.
IntToDoubleFunction celsiusToFahrenheit = celsius -> 1.8 * celsius + 32.0;
System.out.printf(“%d Celsius = %.1f Fahrenheit%n”,
37, celsiusToFahrenheit.applyAsDouble(37));
// 37 Celsius = 98.6 Fahrenheit
13.9 Two-Arity Specialization of Function<T, R>: BiFunction<T, U, R>
The BiFunction<T, U, R> interface is the two-arity specialization of the Function<T, R> interface. In Table 13.8, we see that its functional method apply() has the type (T, U) -> R—that is, it takes two arguments of type T and U, and returns a result of type R.
The following code illustrates defining and using two-arity functions. The twoarity function areaOfRectangle calculates the area of a rectangle.
BiFunction<Double, Double, Double> areaOfRectangle
= (length, width) -> length * width; // (Double, Double) -> Double
System.out.printf(“%.2f x %.2f = %.2f%n”,
25.0, 4.0, areaOfRectangle.apply(25.0, 4.0));
// 25.00 x 4.00 = 100.00
Table 13.8 Two-arity Functions
Functional interface (T, U, and R are type parameters) | Functional method | Default methods |
BiFunction<T, U, R> | apply: (T, U) -> R | andThen() |
ToIntBiFunction<T, U> | applyAsInt: (T, U) -> int | – |
ToLongBiFunction<T, U> | applyAsLong: (T, U) -> long | – |
ToDoubleBiFunction<T, U> | applyAsDouble: (T, U) -> double | – |
The two-arity function concatKeyVal below concatenates two strings and returns a new string as the result. The reference map refers to a HashMap<String, String>. The replaceAll() method called on this map takes the two-arity function concatKeyVal as a parameter, and it replaces the value of each entry (key, value) in the map with the result of the two-arity function applied to the entry—that is, the method call concatKeyVal.apply(key, value) is executed for each entry in the map. The apply() method is implemented by the lambda expression below, resulting in the method call key.concat(value) being executed for each entry.
BiFunction<String, String, String> concatKeyVal = (key, val) -> key.concat(val);
// {Dick=silver, Harriet=platinum, Tom=gold}
map.replaceAll(concatKeyVal);
// {Dick=Dicksilver, Harriet=Harrietplatinum, Tom=Tomgold}
It is instructive to implement and compare the two-arity function above using an anonymous class:
// {Dick=silver, Harriet=platinum, Tom=gold}
map.replaceAll(new BiFunction<String, String, String>() {
public String apply(String key, String val) {
return key.concat(val);
}
});
// {Dick=Dicksilver, Harriet=Harrietplatinum, Tom=Tomgold}