Learning to Use Functional Progamming in Java — How?

Y Paulus Kh
Life At Moka
Published in
3 min readFeb 1, 2020
Photo by Max Duzij on Unsplash

Since the introduction of Java 8, we Java programmers have been blessed with numerous features, ready to use. One of the most talked-about is the addition of the Functional Programming paradigm in Java. Suddenly no more caveman jokes about us, dwindling in our cubicle and sipping instant coffee, we are ready for the 21st century.

I’m not an exception, putting my brain into turbocharged learning mode, trying to reinvent myself as a modern programmer in order to fully understand the whole features of Stream API and Lambda Expression.

Some things that I learned that Java 8 enables us to code in more compact, simpler, less verbose ways. We can reduce the number of code lines significantly.

However some ways are best to be left alone, some programming cases are better to be written in the old ways.

Now in Moka, we face many cases with converting plain old Java codes to functional programming. These are some examples that I gathered over the years:

First, How to find any matched condition and change a flag

boolean zeroFound = false;
for (Long itemVariantId : itemVariantIds) {
if (itemVariantId.equals(0L)) {
zeroFound = true;
break;
}
}

Code above can be written like this

boolean zeroFound = itemVariantIds.stream()
.anyMatch(itemVariantId -> itemVariantId.equals(0L));

Using anyMatch is self explanatory, just put lambda expression with desired condition and voila!

Now code above gives significant impact in terms of line of codes. Clearly using Java Stream for this case is desirable if not, a necessity. But now we’ll try to look at some of more complicated idea.

for (SalesCheckoutDTO salesCheckout : 
salesCreateRequestDTO.getSalesCheckout()) {
if (salesCheckout.getIsRecipe()
&& salesCheckout.getItem() != null) {
salesCheckout.setItemId(salesCheckout.getItemId());
break;
}
}

Code above can be written like this:

salesCreateRequestDTO.getSalesCheckout().stream()
.filter(SalesCheckoutDTO::getIsRecipe)
.map(SalesCheckoutDTO::getItemId)
.findFirst()
.ifPresent(salesCheckoutDTO::setItemId);

It’s probably more compact but somehow for those who’s not familiar with functional programming that code is not easily readable. I think the problem is with the chain of Stream’s method like filter and map , something that’s strange in the mind of old school Java programmer.

Is it really that hard or we’re stuck too long in object — oriented paradigm that passing method references and functions is too foreign for us?

It seems that we can break down the solution into two areas : syntax and paradigm.

Now, how do we tweak the code so we can understand the implementation of functional programming in Java easily?

  1. Use proper code formatter: Avoid writing Stream method chaining code without any line break. Try separating method with a line break, it will increase readability. Some code formatter comes with a default setting that makes the code chains without line breaks, try editing the format if possible.
  2. Install Sonar Lint: Sonar Lint is an IDE plugin to make sure that your code is optimized and clean. It highlights bug-prone and vulnerability code and providing optimization lambda expression.

Next, the hard part, changing our mind in order to grasp the concept of functional programming better.

  1. Increase your Flight Hour: Try implementing Lambda Expression in your code whenever feasible. It’s classic but experiences don’t come without hours of practice.
  2. Experimenting with Anonymous Inner Class: Lambda expression in Java can be translated from an anonymous inner class since the later is the original implementation of passing a function as an argument. Try writing code using anonymous inner class first then using your IDE tool to convert that into lambda expression or method reference if possible — I’m using IntelliJ and used to use Eclipse, both have the tool. By using both of them we can understand the magic and rules behind, how things convert to another.
  3. Try Subtlety: When you feel that using Stream in certain conditions is not feasible and adding no value, leave it in the old way. Do not push new things into every mouth.

Now you’re ready to start walking in the path of functional programming. It might take extra effort to do it, it’s not an easy feat, but it’s worth learning. In the end, this is not about right or wrong, but rather what methods suits you best for the condition you facing.

--

--

Y Paulus Kh
Life At Moka

A programming enthusiast, currently working as software engineer for a growing startup. Interested in technology, programming, and cooking.