Java 8 has been around since March this year and I finally have gotten around to playing with it and in particular the functional programming aspects.
I have seen people using these aspects through the Google Guava libraries but the huge number of nested classes messed up the code, adding a lot of clutter.
As can be seen from the below example, lambda expressions help get rid of the clutter. Further, what I really liked is that, if correctly used and I am no guru yet, it results in better code, which can tick all the boxes of the SOLID design principles.
Prior to Java 8
Breaking it down
* stream() - I see the result of this method to be analogous to the pipe on a UNIX shell, creating a pipeline of stages of processing. It returns a sequence of values to be consumed either in serial or parallel.
* map(Function<InputType, OutputType>) - applies the function to convert the input to output and returns a stream of output values.There are other inbuilt map functions like mapToInt(), mapToLong() and mapToDouble()
*reduce() - in this case, reduces two operands into one masked value and repeatedly does this until there is only one result left. The operation needs to be associative as this could be executed in parallel.
I have seen people using these aspects through the Google Guava libraries but the huge number of nested classes messed up the code, adding a lot of clutter.
As can be seen from the below example, lambda expressions help get rid of the clutter. Further, what I really liked is that, if correctly used and I am no guru yet, it results in better code, which can tick all the boxes of the SOLID design principles.
Prior to Java 8
import java.util.ArrayList;
import java.util.List;
enum DecimalStringToBinaryMaskEnumMap {
ZERO(0), ONE(1 << 0), TWO(1 << 1), FOUR(1 << 2), EIGHT(1 << 3), SIXTEEN(
1 << 4);
public static int getBinaryMaskFor(String value) {
return DecimalStringToBinaryMaskEnumMap.valueOf(value).getBinaryValue();
}
public int getBinaryValue() {
return binary;
}
private DecimalStringToBinaryMaskEnumMap(int binary) {
this.binary = binary;
}
private int binary;
}
public class EnumMask {
public int getMask(final List<String> decimalValues) {
int mask = 0;
for (final String decimalVal : decimalValues) {
mask |= DecimalStringToBinaryMaskEnumMap.valueOf(decimalVal).getBinaryValue();
}
return mask;
}
public static void main(String[] args) {
final List<String> decimalValues = new ArrayList<>();
decimalValues.add("TWO");
decimalValues.add("EIGHT");
System.out.println(new EnumMask().getMask(decimalValues));
}
}
Applying Java 8's functional programming idioms, we can replace the getMask function as belowpublic static final Function<String, Integer> stringToBinaryMaskIntegerFunction = valueString -> DecimalStringToBinaryMaskEnumMap
.getBinaryMaskFor(valueString);
public int getMask(final List<String> decimalValues) {
return decimalValues.stream().
map(stringToBinaryMaskIntegerFunction).
reduce(0, (a,b) -> a | b);
}
Breaking it down
* stream() - I see the result of this method to be analogous to the pipe on a UNIX shell, creating a pipeline of stages of processing. It returns a sequence of values to be consumed either in serial or parallel.
* map(Function<InputType, OutputType>) - applies the function to convert the input to output and returns a stream of output values.There are other inbuilt map functions like mapToInt(), mapToLong() and mapToDouble()
*reduce() - in this case, reduces two operands into one masked value and repeatedly does this until there is only one result left. The operation needs to be associative as this could be executed in parallel.