Thinking beyond Java 8

Rapid evolution of Java

Java 9 was released in September 2017. Six months later came Java 10. Since then, a new version of Java gets released every six months. The latest version is Java 17, released in September 2021, this year.

The Java platform is evolving at a rapid pace. With every release, we get several updates and capabilities provided by the Java language and the platform. These changes can have a solid impact on our productivity and the performance of our application.

New Course on Udemy – Thinking Beyond Java 8

So in case you are a Java developer wanting to catch up with the ever-evolving Java language and platform or wish to learn the new features of modern Java, I just released my second course on Udemy that will help you do the same.

In this course, we begin our journey from Java 9 and move step by step through every release up to Java 17 and discover:

  • Language Features
  • Changes in the String class, Stream API
  • Garbage collectors like G1, ZGC, Epsilon, Shenandoah
  • Productivity tools like JShell, Java Flight Recorder, and more
  • Java Microbenchmark Harness
  • Performance-related improvements
  • Removals & deprecations
  • Modularity, jdeps, jlink, jdeprscan and
  • Much more!

Want to know more about the course?

Check out the course landing page and the preview videos to learn more about the course.

Prerequisites

The only prerequisite is that you have some programming experience with Java 8 since some code examples contain Lambdas and Streams code. Besides this, we use Maven only for a handful of lectures.

I’d love to have you on board with this course!

Decorator Pattern using Java 8

In this post we are going to look at a couple of examples which use the GoF Decorator pattern. We will then refactor this code to use some of the features introduced in Java 8 which give Java a taste of functional programming. After this refactoring, we will see if the refactored code showcasing the decorator pattern becomes concise and easy to understand or makes it more complicated.

The basic idea behind the decorator pattern is that it allows us to add behavior to an object without affecting or modifying the interface of the class. I would suggest you to read and get a basic idea about the Decorator pattern in case you are completely unaware of it.

I would be considering 2 existing posts showcasing the decorator pattern and then we would be refactoring the code using Java 8.

Typical Decorator – Example one

The first example that we are going to look at is a code sample that I saw from a site, codeofdoom.com, which unfortunately does not exist anymore(domain seems to have expired). That post referred to an example which was simple to read and showed how a typical decorator pattern is implemented. I thought I had understood the pattern but I was mistaken.

The requirement in that example

The requirement that I understood from the code – We need to format a particular text supplied as input. The formatting can be one of several options- we return the text as it is, format the text to upper case, replace a word in the text with another word , concatenation of text with another string or a permutation and combination of the options. I have stated the requirements upfront but usually as developers we are never aware of the requirements upfront and requirements always keep changing. It would not make sense to create separate classes for each permutation – combination. In such situations, the decorator pattern can be extremely useful.

The example mentioned has an interface Text and a basic implementation of the same which returns the text. There are 3 classes AllCaps, StringConcat and ReplaceThisWithThat which are decorators taking the input text and adding specific behavior to it. The advantage of using the decorator pattern here is that we can use and combine 1 or more decorators to achieve formatting of the input text dynamically rather than sub-classing and creating different combinations of the sub-classes.However the implementation of a typical decorator is not so straightforward to understand. I had to debug a little bit to get a good understanding of how the code really decorates the object.

So let’s define an interface Text with a method format as shown below –

public interface Text {
    public String format(String s);
}

The BaseText class simply returns the text as is –

public class BaseText implements Text{

    public String format(String s){
        return s;
    }
}

The TextDecorator class serves as base decorator class which other classes extend. This decorator class is like a core class which helps in combining different functionalities.

public abstract class TextDecorator implements Text {

    private Text text;

    public TextDecorator(Text text) {
        this.text = text;
    }

    public abstract String format(String s);
}

The AllCaps class takes the input and formats it to uppercase –

public class AllCaps extends TextDecorator{

    public AllCaps(Text text){
        super(text);
    }

    public String format(String s){
        return text.format(s).toUpperCase();
    }
}

The StringConcat class calls format and then concatenates the input string –

public class StringConcat extends TextDecorator{

    public StringConcat(Text text){
        super(text);
    }

    public String format(String s){
        return text.format(s).concat(s);
    }
}

And finally, the class which replaces text “this” with “that” –

public class ReplaceThisWithThat extends TextDecorator{

    public ReplaceThisWithThat(Text text){
        super(text);
    }

    public String format(String s){
        return text.format(s).replaceAll("this","that");
    }
}

Test class to run the decorators –

public class TextDecoratorRunner{

    public static void main(String args[]){

        Text baseText = new BaseText();
                
        Text t = new ReplaceThisWithThat(new StringConcat(new AllCaps(baseText)) );

        System.out.println(t.format("this is some random text"));
    }
}

Notice how the call is done. It is actually inside-out but the code is read from the outside-in.

A pixel is worth 1024 bits
Flow of the Decorator pattern

The left hand side shows the calls to the format method in each decorator class and the right hand side shows how the decorators hold references or how they are chained.

The final output from this is – THIS IS SOME RANDOM TEXTthat is some random text.

Refactoring the decorator pattern using Java 8

Well, now to the main task of re-implementing the same using functional style. The BaseText class shown above has a function, format, which simply takes a String and returns a String. This can be represented using functional interface, Function<String,String> – introduced in Java 8.

import java.util.function.Function;

public class BaseText implements Function<String,String>{

    public BaseText(){
    }

    @Override
    public String apply(String t) {
        return t;
    }
}

Now, each decorator class implements a simple functionality of formatting a string in different ways and can be combined as shown below in a single class using static methods.

public class TextDecorators
{

    public static String allCaps(String s){
        return s.toUpperCase();
    }

    public static String concat(String input) {
        return input.concat("this is some random text");
    }

    public static String thisWithWhat(String input) {
        return input.replaceAll("this", "that");
    }

}

This simply leads us to the following –

public class TextDecoratorRunner {

    public static void main(String[] args) {
        String finalString = new BaseText()
                .andThen(TextDecorators::allCaps)
                .andThen(TextDecorators::concat)
                .andThen(TextDecorators::thisWithWhat)
                .apply("this is some random text");

        System.out.println(finalString);
    }
}

The code above does function chaining and uses method reference. It takes the text and passes it through a chain of functions which act as decorators. Each function applies a decoration and passes the decorated string as output to the next function which treats it as an input.  In this scenario, there is no need to have separate classes which act as decorators or the abstract base class. This implementation offers the same flexibility as the typical solution but I think it is also much much easier to understand as compared to the typical way of implementing the decorator pattern. There is also no inside-out or outside-in business when we call the function.

Typical Decorator – Example two

The second example that we are going to consider is shown here groovy decorator.  I would suggest you to read it to get a basic understanding of the use case. Also note the confusion between whether the complete text is logged in upper case or timestamp is logged in lower case.

Decorator pattern refactored

Let us try and use the same concept of function chaining to refactor this.

The code for the Logger interface would look like this –

public interface Logger {
	public void log(String message);
}

The SimpleLogger class –

public class SimpleLogger implements Logger {

	@Override
	public void log(String message) {
		System.out.println(message);

	}
}

The individual decorated logger can be represented as below –

import java.util.Calendar;

public class Loggers {
	
	public static String withTimeStamp(String message){
		
		Calendar now = Calendar.getInstance(); 
		return now.getTime() + ": "+  message;
	}
	
	public static String uppperCase(String message){
		
		return message.toUpperCase();
	}
}

And finally using function chaining –

import java.util.function.Function;
import java.util.stream.Stream;

public class LoggerTest {
	public static void main(String[] args) {

Logger logger = new SimpleLogger();

        Function<String,String> decorators = Stream.<Function<String,String>>of(Loggers::withTimeStamp,Loggers::uppperCase)
                .reduce(Function.identity(),Function::andThen);

        logger.log(decorators.apply("G'day Mate"));

	}
}

The code above looks a little daunting at first glance but it is actually simple, let us break it down –

Lines 9- 12 are the key to understanding this. I am using Stream.of and passing method references which are individual decorators.

  1. To combine them or to chain them, we use the Stream.of. The Function<String,String> in Stream.<Function<String,String>>of  is more of a compilation thing , to represent the Stream that the output is a Function<String,String>.  Using the Stream.of, we are forming a chain of functions.
  2. Now to the reduce part, the reduce part chains all of them together to form a single function. What do we want to do with each function as they come out from the stream ? We want to combine them, this is done using the andThen, that is exactly done in the 2nd parameter to the reduce function.  The first parameter to the reduce method is an initial value, this is the identity function – given a function, just return the function. Every reduction needs a starting point. In this case, the starting point is the function itself.
  3. The chaining yields a Function<String,String> decorators.
  4. We just call the apply method to this using the parameter G’day Mate which passes it through the chain of functions( decorators) and finally sends that to the logger.log method.

This version of the decorator pattern is easier to understand, we simply took a message, added the timestamp to it , converted it to upper case and logged it.The Stream.of and the methods references being passed to it might seem difficult at the first read, but trust me it is more of a new way of solving the problem and an easier one in my opinion.

Conclusion

We took 2 examples of the decorator pattern but both examples have clarified that there is certainly an easier and better way to implement the decorator pattern. In both cases the decorator pattern using the functional style is definitely more concise and easier to understand. Code that is easier to understand is always easy to maintain. Can we safely conclude that we probably don’t need the typical decorator pattern anymore?

Well, in the examples that we considered, we had just one method or one functionality to decorate, the format method in the first example and log method in the second example. In these scenarios, the functional style definitely seems better and there is no need to go about creating different classes, the abstract class and then use the cryptic way of calling them. But what if we had more than a single method to decorate ? This is something that needs to be looked at and I will try and answer that in another post.

Java 8 default methods – Basic introduction

Let us assume that you have designed, published a library and you have many clients who use your library. You have followed the “Object Oriented” concepts and hence made use of interfaces, abstract classes, util classes to design your library.

After a few years, you realize that the core library is quite old, they need to move ahead with time and hence you would like to add new features to this library. At the same time you do not want your existing clients knocking at your door at 2:00 am in the morning to complain about a new piece of functionality you added which broke their existing code.

What are the possible solutions to this?

  1. Have a new interface define these methods, introduce an abstract class  to implement the interface and provide some skeletal behavior for the new functionality. This is actually a design technique that has been used in the Collection framework – The problem here is that we have abstract classes which mean that the existing client cannot extend from more than 1 class. 
  2. Classes with static methods – The problem here is that the clients cannot override the functionality if they would like to. This means clients will have to use the single implementation which does not really give them flexibility.

So how do we achieve all of the following?

  1. Add new functionality to an old library.
  2. Not break existing client code.
  3. Allow clients to inherit behavior and not state
  4. Allow clients to override behavior if needed

The answer to this is the default methods. A default method can be directly added to an interface with an implementation. Yes, you read that right! Interfaces with methods and not just the declaration but definition as well.

public interface ExistingInterface {
public void connect();
public void disconnect();
//Default method.
public default void connectUsingNewProtocol(){
System.out.println("Connection to a new device");
}
}

Some examples in the Java library which use the the default method:

1) stream method in the Collection interface – Enables any collection to be streamed.

    default Stream<E> stream() {
        return ...;
    }

2) reversed method in the Comparator interface – Enables reversing of the comparator

    default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

3) forEach and spliterator in the Iterable interface

One purpose of the default methods was to make changes to the Collection framework without breaking other libraries that use Collection API, like the Apache CollectionUtils or Hibernate and at the same time provide us with new functionality.

We all know that an interface can extend from another interface in Java.  By adding default methods, things get a little complicated and hence there are some things to remember when using default methods:

In the code below, Parent interface has default methods, Child extends from Parent but does not provide implementation.

interface Parent {
default public void methodOne() {
System.out.println("Method one…");
}
default public void methodTwo() {
System.out.println("Method two…");
}
}
interface Child extends Parent{
}
public class ConcreteClass implements Child {
public static void main(String[] args)
{
ConcreteClass concreteClass = new ConcreteClass();
concreteClass.methodOne();
concreteClass.methodTwo();
}
}
}

Output:

Method one…

Method two…

Conclusion : Default methods are inherited in the Child interface.

In the next example below :

Parent interface has default method, Child extends from Parent and does provide or override implementation.

interface Parent
{
default public void methodOne() {
System.out.println("Parent : Method one…");
}
default public void methodTwo() {
System.out.println("Parent : Method two…");
}
}
interface Child extends Parent
{
//overrides methodTwo
default public void methodTwo(){
System.out.println("Child : Method two…");
}
}
public class ConcreteClass implements Child
{
public static void main(String[] args)
{
ConcreteClass concreteClass = new ConcreteClass ();
concreteClass.methodOne();
concreteClass.methodTwo();
}
}

Output:

Parent: Method one…

Child: Method two…

Conclusion:The most specific/ the one at the bottom in the interface hierarchy wins!

What if the ConcreteClass class also provided the implementation for the methodTwo() above ?

public class ConcreteClass implements Child {
public void methodTwo(){
System.out.println("ConcreteClass : Method two…");
}
public static void main(String[] args) {
ConcreteClass concreteClass = new ConcreteClass ();
concreteClass.methodOne();
concreteClass.methodTwo();
}
}

Output:

Parent: Method one…

ConcreteClass: Method two…

Conclusion : Class wins over interface hierarchy!

What happens when we have same default methods in 2 “unrelated” interface and 1 concrete class implementing the 2 interfaces

interface One {
default public void callMe(){
System.out.println("One:callMe…");
}
}
interface Two
{
default public void callMe()
{
System.out.println("Two:callMe…");
}
}
public class ConcreteClass implements One, Two
{
public static void main(String[] args)
{
}
}

Output: The java compiler complains that the method callMe is being inherited from types One and Two. Well, it is our responsibility to resolve the same. This can be done in the following way:

public class ConcreteClass implements One, Two
{
@Override
public void callMe()
{
One.super.callMe();
}
public static void main(String[] args)
{
ConcreteClass concreteClass = new ConcreteClass();
concreteClass.callMe();
}
}

Depending on the implementation of the default method, we can either call the version One or the Two. This is done by using the super keyword. Without using the super keyword, it would mean we are calling the static method on the interface which is not the case here.  At the byte code level , this translates to a invokespecial instruction.

To summarize

  1. Interface hierarchy – the most specific wins
  2. Classes always win in case there is a class that implements a default method and there is an interface hierarchy.
  3. If there is still a problem, it is the responsibility of the developer to resolve it as shown above.

So, does this mean that we do not need abstract classes anymore? Well, that is not right.  What clearly distinguishes the two is state and the fact that a class can inherit only 1 class

So interfaces are always a better idea unless we need state or a skeletal implementation.

Java 8 : Imperative vs Declarative style of coding

The focus of this article is to compare the imperative style of solving a problem vs declarative style using a couple of examples.It assumes basic knowledge about Lambdas and Streams introduced in Java 8.

Example 1:   I do not wish to give you the problem statement on purpose. Look at the code below and try to figure out the intention of the code.


List<Player> validPlayers = new ArrayList<>();
FootballLeague premierLeague = null;
for(FootballLeague league:leagues)
{
if(league.getLeagueName() == LeagueName.PREMIER_LEAGUE )
{
premierLeague = league;
break;
}
}
if(null != premierLeague)
{
List<Player> players = premierLeague.getPlayers();
for(Player player: players)
{
if(player.getAge() <= 25)
{
validPlayers.add(player);
}
}
}
Collections.sort(validPlayers, new Comparator<Player>() {
@Override
public int compare(Player p1, Player p2 ) {
return p1.getName().compareTo(p2.getName());
}
});
StringBuilder builder = new StringBuilder();
for(Player player : validPlayers)
{
builder.append( player.getName()+ ",");
}
return builder.substring(0,builder.length()-1);

I am sure you read that code very carefully and possibly a couple of times. What does it do? You might read it again ! Most developers have a short memory. You know that you might have to revisit this code at some point and hence you will probably add comments in the code above like sort by name , remove last comma etc.

From a list of football leagues, the code checks if the league is the English Premier league, selects all the players who play for the English premier league where their age is <= 25 years. It then sorts them by their names and then finally returns a comma separated list of their names.

So our problem statement:  Given a list of football leagues, select all the players who play for the English Premier League and are <=25 years of age. Then sort their names and return them as comma separated.  Let us break this problem statement about what we want to do:

  1. Select all the players who play in the Premier league
  2. Remove all the players who are above 25 years of age
  3. Sort the names of the players
  4. Get their name and make them comma separated

Let us code this now using declarative style.

Declarative style:


return leagues.stream()
.filter(league -> league.getLeagueName() == LeagueName.PREMIER_LEAGUE)
.flatMap(league ->league.getPlayers().stream())
.filter(player -> player.getAge() <=25)
.sorted(Comparator.comparing(Player::getName))
.map(player ->player.getName())
.collect(Collectors.joining(","));

Look at the code above and the problem statements from 1-4. Don’t you think that the code above reads more like the problem statement? Not only does it read like the problem statement, the code does not have any garbage variables, no for loops instructing how we want to iterate and select. We are focusing more on what we want rather how we want to do it. Hence it is also easier to make any changes to the code in case the requirements change which means the maintenance is easy.  

We could have used a .sorted(Comparator.naturalOrder()) above and done the mapping to get the name first before sorting.


return leagues.stream()
.filter(league -> league.getLeagueName() == LeagueName.PREMIER_LEAGUE)
.flatMap(league ->league.getPlayers().stream())
.filter(player -> player.getAge() <=25)
.map(player ->player.getName())
.sorted(Comparator.naturalOrder())
.collect(Collectors.joining(","));

Example 2:  Given a list of strings,we need to output the strings based on their length. If the input string is “I”, ”ate”, ”food”, ”slept”. The output should be

1 – I

3-ate

4-food,slept

Imperative style:


Map<Integer, List<String>> lengthMap = new HashMap<>();
for(String string : strings)
{
List<String> sameLength = null;
Integer length = string.length();
if(lengthMap.get(length) == null)
{
sameLength = new ArrayList<>();
sameLength.add(string);
lengthMap.put(length, sameLength);
}else
{
List<String> sameLengthString = lengthMap.get(length);
sameLengthString.add(string);
}
}
return lengthMap;

Hmm, one thing is clear that we need a Hashmap. The key will be the length of string and the value will be the actual string. So what are we doing here

  1. Create a new hashmap
  2. Iterate through the list of strings
  3. Create  a new list
  4. If the current string has length x and x is already in the map then get the list corresponding to the length and add the current string to that list, else
  5. Create a new list and add the length of string and the string length as key , value as actual string.
  6. Done !

In short, we are grouping strings by their length.

Declarative style:


return strings.stream()
.collect(Collectors.groupingBy(String::length)));

What are we doing here:

  1. Group all the strings by length
  2. Done !

Again, the code is expressive and it translates to the problem statement very clearly !

The Collectors.groupingBy method returns a Map of Integer, List<String> or K, V where

K- the type that we are grouping by

V – The elements that we are operating on ( in this case, String)

Note that we have not considered the case where strings can repeat. This can be solved easily by using a Set instead of a List which would be pretty easy in both imperative and declarative style.

Declarative style does make your code more readable and concise.Declarative code might not be the magical solution to all problems, if you find the declarative style getting too complicated, stick to the old imperative style of programming.

Sorting a list in Java with null values

I am going to tell you a story with 2 characters, the developer and the quality analyst(QA). The developer is working on  a very simple application which deals with teenagers and the brand of cell phone they use.

I think the relation between developers and QA is like a one night stand, well, not the typical one! One fine day the QA finds bugs and thanks to your manager (who leaves home early), the developer and the QA are made to stay back and work all night until the bug is fixed and the code is completely bug free.(Yeah, right !)

Our developer friend has written a Teenager class which has an age field and a phoneBrand field.


public class Teenager {
private int age;
private String phoneBrand;
//getters,setters
}

view raw

Teenager.java

hosted with ❤ by GitHub

Manager: We have a new requirement,there is a need for a survey and hence the application needs to return the list of teenagers by increasing age. If two teenagers have the same age, then we need to return the list considering the brand of the cell phones in alphabetical order.

Developer: This will take time. I need to make sure that I write the code using Object Oriented Principles.

Manager: Alright, I give you a days time.( You know he does not understand Object oriented principles !)

You bring all your Object oriented skills to the table, create a separate class for the comparator as the sorting is done using 2 different fields, the age field and then the phoneBrand field. The comparator class looks like this:


public class TeenageSorter implements Comparator<Teenager>{
@Override
public int compare(Teenager t1, Teenager t2)
{
if( t1.getAge() == t2.getAge())
{
return (t1.getPhoneBrand().compareTo(t2.getPhoneBrand()));
}
return t1.getAge() > t2.getAge()? 1 : –1;
}
}

The input to your sort function is a List of Teenagers. You call the sort method like this:

Collections.sort(teens, new TeenageSorter());

Everything works fine.Given an input like this:


List<Teenager> teens = new ArrayList<>();
teens.add(new Teenager(15,"Apple"));
teens.add(new Teenager(16,"Samsung"));
teens.add(new Teenager(14,"Xiaomi"));
teens.add(new Teenager(16,"Apple"));

Output:

[Age:14 |Phone:Xiaomi, Age:15 |Phone:Apple, Age:16 |Phone:Apple, Age:16 |Phone:Samsung]

Sorted by increasing age and as there are 2 teenagers aged 16, the one with the Apple phone is followed by Samsung using alphabetical order. You check in the code and inform your manager that you are done with your task.

A few hours later, at around 6 pm when you are just about to leave, the QA guy comes to your desk.

QA : Your code is not working .

Developer : That is not possible ![Unpleasant stare]

QA : I am not sure, I added a teenager but did not give him a phone !

You think about it for a second, your coding skills (spelt  “ego”) are at stake, you have to come up with a reply.You know you left that part in the code but…

Developer: How can a teenager not have a phone ! [ You know in your heart that you never had a cell phone as a teenager]

QA : Well, yes, all teenagers do but currently our system allows me to do that, I followed the steps, kept the brand name of the phone empty, it crashed !

Well, you take a deep breath.You know you assumed that the data will never be null. You got what you deserved , a null pointer exception !

You go to your manager and tell him that it is possible that a teenager might not have a phone, so the requirement has to be discussed now. You involve the business analyst as well and explain the situation. The analyst says, well, if a teenager does not have a cell phone and two teenagers have the same age, we need to put them at the end of the list.

You have been asked to fix this in the next few hours.You start thinking about this problem. If the teenager does not have a phone, it means the phoneBrand field is null. Hence the sorting has to now deal with nulls.You look at your Comparator and this is what you come up with:


public class TeenageSorter implements Comparator<Teenager>{
@Override
public int compare(Teenager t1, Teenager t2) {
if( t1.getAge() == t2.getAge()){
return sortByPhoneBrand(t1.getPhoneBrand(),t2.getPhoneBrand());
}
return t1.getAge() > t2.getAge()? 1 : –1;
}
private int sortByPhoneBrand(String phoneBrand1,String phoneBrand2){
if(phoneBrand1 == null && phoneBrand2 == null){
return 0;
}
if(phoneBrand1 == null && phoneBrand2 != null){
return 1;
}
if(phoneBrand1 != null && phoneBrand2 == null){
return1;
}
return phoneBrand1.compareTo(phoneBrand2);
}
}

A shiny new method to sort the phoneBrand. This time when you test your code, you supply the following input:


List<Teenager> teens = new ArrayList<>();
teens.add(new Teenager(15,"Apple"));
teens.add(new Teenager(16,"Samsung"));
teens.add(new Teenager(14,"Xiaomi"));
teens.add(new Teenager(14,"Samsung"));
teens.add(new Teenager(16,"Apple"));
teens.add(new Teenager(16,null));

Output:

[Age:14 |Phone:Samsung, Age:14 |Phone:Xiaomi, Age:15 |Phone:Apple, Age:16 |Phone:Apple, Age:16 |Phone:Samsung, Age:16 |Phone:null]

The list above is sorted by increasing age. When the age is the same,16, the teenager without the phone gets pushed to the end of the list as if the teenager is not wanted. You check in the code and leave for the day (night?)  and you are still feeling bad that the teenager does not have a phone.

The next morning, the QA does his testing, things are working fine!

QA : Everything is fine now.

Developer : Yes, I know !  [Arrogance is the key, isn’t it ! ]

Is there a chance to refactor your code ? You look at your code and ask yourself if you can refactor that code somehow. The comparator methods do not really look that clean. It is kind of buggy. It is not that clear when nulls starting popping up, should you return a 1 or a -1 ? It is more like trial and error at times. Imagine what happens if you are asked to sort by another field in addition to the 2 fields above? What if we add another field, earphoneBrand. If two teens are aged the same, have the same phone then sort by the brand of the ear phones. What if someone does not have earphones ?

You remember reading about Lambdas in Java 8 and start exploring if they made any changes to the Comparator interface. On further reading, you actually discover a lot and come up with the following analysis:

  1. Comparator present in the java.util.package is a functional interface and hence..
  2. Usage of the anonymous inner class can be replaced with usage of Lambdas.
  3. There are default methods in the Comparator interface now which can also sort objects if they are null.

So let us revisit the problem statement:

Given a list of Teenagers:

a) sort the list by age first

b) if age is the same then sort by phone brand name and

c) if the teenager does not have a phone(null), then it should be kept at the end for that particular age.

Declarative style:


Collections.sort(teens,
Comparator.comparing(Teenager::getAge)
.thenComparing(Teenager::getPhoneBrand,Comparator.nullsLast(Comparator.naturalOrder())));

What ? What is that ? Let us break that down a little bit, following a, b and c above.


Comparator<Teenager> phoneBrandPossibleNulls =
Comparator.comparing(Teenager::getPhoneBrand,Comparator.nullsLast(Comparator.naturalOrder()));
Collections.sort(teens, Comparator.comparing(Teenager::getAge)
.thenComparing(phoneBrandPossibleNulls));

The code on lines 1 and 2 creates a comparator to sort by the phone brand and instructs how to deal with null values. Line 4 combines the two, if the age is the same then compare with the phone brand. The part, Comparator.nullsLast(Comparator.naturalOrder()) means that when we get 2 phoneBrand objects, we can have various combinations. Both null, one of them null and none of them null. The code says, use natural order for sorting phoneBrand fields and if you encounter a null, then put them at the end of the list.

I must admit the code does need a little bit of explanation this time, but it is still expressive enough and probably takes getting used to the function composition part. But the code flows well, any kind of changes to it are quite easy rather than the imperative style. The focus is more on what you want. If you get a new requirement of putting the teenager without a phone at the beginning of the list, all we need to do is modify the code to use Comparator.nullsFirst above. If we need to sort by another field, add another thenComparing().

You are so enthusiastic about Java 8 but then it dawns upon you that your manager has not yet approved that you switch to Java 8 and you are still coding with an old version. Well, send him an email and tell him that you feel like this:

outdated1

 

Well, if you are still stuck with prior versions of Java , there are other libraries to do that. One solution is to use the Google Guava libraries. The Google Guava library has something similar to the Java 8 style of composing functions.It uses chaining of comparators like above.


Collections.sort(teens,new Comparator<Teenager>() {
@Override
public int compare(Teenager t1, Teenager t2)
{
return
ComparisonChain.start()
.compare(t1.getAge(), t2.getAge())
.compare(t1.getPhoneBrand(), t2.getPhoneBrand(),Ordering.natural().nullsLast())
.result();
}
});

This chaining is not very different from the Java 8 style, in fact a few things in the Google Guava library have served as an inspiration to the designers of the JDK library. So if you cannot switch to Java 8 yet, you could use the google guava version, it is much cleaner that writing a comparator of your own with all null checks and other checks.

It has been a couple of days since you checked in the code, things seem quiet, the QA, Business Analyst and the Manager, nobody has turned up at your desk. It means everything is working fine !

Java 8 map and flatMap

In this post, we will be taking a look at the map and flatMap methods introduced in Java 8. We will be looking at a scenario where the map method does not produce the required output and why we really need the flatMap method. I will be using multiple examples to illustrate the same and also show you imperative and declarative styles of coding.

map: Let us consider the scenario where we have a collection of Person objects. Given a list of person objects, what if we wanted to return only the names of the people who have UK citizenship.

The imperative style of writing code would give us the following:


public List<String> getNamesOfUKCitizens(List<Person> persons)
{
List<String> allUKCitizens = new ArrayList<>();
for(Person p : persons)
{
if(p.getCitizenship() == Citizenship.UK){
allUKCitizens.add(p.getName());
}
}
return allUKCitizens;
}

To get this, we have to initialize an empty list, iterate through the loop, filter the people who have UK citizenship and then add the names to the empty list we create.Let’s try and solve this the  declarative way, using the map method.

The map method basically takes an object of one type and gives us an object of another type.


public List<String> getNamesOfUKCitizens()
{
return persons.stream()
.filter( p -> p.getCitizenship() == Citizenship.UK)
.map(p -> p.getName())
.collect(Collectors.toList());
}

Map_Flatmap_Pic1
filter,map and collect – Once the knob is turned on, everything happens !

The signature of the map method:

<R> Stream<R> map(Function<? super T,? extends R> mapper)

The signature looks complicated but it is easy to understand. The R is the output type of the stream and T is the input type.

Remember how the filter method (explained here) took a Predicate as a parameter? The map method takes a Function. This is also a functional interface. The function gets applied to each element. The p -> p.getName is a lambda expression, the function that gets applied to the Person object.  To understand this better, we could write the same thing as follows:


public List<String> getNamesOfUKCitizens()
{
Function<Person,String> mapper = p -> p.getName();
return persons.stream()
.filter( p -> p.getCitizenship() == Citizenship.UK)
.map(mapper)
.collect(Collectors.toList());
}

Remember that the map method takes one object and returns exactly one object. This is 1-1.

Few more examples of map API:

1.Given a list of numbers, we want to generate the square of each number:

We have input as a list of numbers of 1 type and we want to transform it:

Input: List<Integer> numbers = Arrays.asList(1,2,3,4,5);


numbers.stream()
.map( number -> number * 2)
.collect(Collectors.toList());

 Output:

[2, 4, 6, 8, 10]

2. Given a list of string, convert each string to upper case:

Transformation of one type to another, this time String to String – use map function

Input:

List<String> strings = Arrays.asList(“abc”,”pqr”,”xyz”);


strings.stream()
.map(s -> s.toUpperCase())
.collect(Collectors.toList()));

Output:  [ABC, PQR, XYZ]

3.Given a list of string, find the length of each string:

Input:

List<String> strings = Arrays.asList(“abc”,”pqr”,”xyz”);

Input to the map is a string and output is the length of each string.


strings.stream()
.map(s -> s.length())
.collect(Collectors.toList()));

Output: [3, 3, 3]

FlatMap: To understand the flatMap, let us consider a different example. Let us consider there are 3 systems and each system returns a list of strings. There is an application which combines these lists and sends the data back to us. Our system needs to take this input and generate all the strings as a single output.

List<String> system1 = Arrays.asList(“AB”,”cd”,”EF”);

List<String> system2 = Arrays.asList(“GH”,”ij”);

List<String> system3 = Arrays.asList(“kl”,”MN”,”op”);

//Combination

List<List<String>> input = Arrays.asList(system1,system2,system3);

Attempt 1: The input type is a List of List<String>.  We want to get all the strings from this input. We know that the map function helps us to transform an object. Will it help us here?  Let us take this step by step.


input.stream()
.map(list -> list)
.forEach(System.out::println)

The call to the input.stream()  returns a Stream<List<String>>

This gives an output:

[AB, CD, EF]

[GH, ij]

[kl, MN, op]

When we apply the map function, each time we are getting a list. But we need the individual elements in that list as a combined result. How do we get that?

When we have a single list as shown below and we applied the stream() to method to it, what happened?

List<String> strings = Arrays.asList(“A”,”b”,”C”);

strings.stream()

              .forEach(System.out::println);

This gave us the individual elements in that stream. So will applying the stream method to the list above solve the issue? Let’s try

Attempt 2:  Applying a stream to the list and using a map


input.stream()
.map(list -> list.stream())
.forEach(System.out::println)

This gives a weird output like this:

java.util.stream.ReferencePipeline$Head@87aac27

java.util.stream.ReferencePipeline$Head@3e3abc88

java.util.stream.ReferencePipeline$Head@6ce253f1

This gives us a stream of objects. So the usage of the map method in this scenario is not right. This is because the map method as mentioned earlier takes an input and produces one output. But in this case, the map method takes a list and we want the individual elements of that list to be combined together. This is not what the map function does. We need to use a different function.

Attempt 3: Using a flatMap


input.stream()
.flatMap(list -> list.stream())
.forEach(System.out::println);

This gives us the required output:

AB

cd

EF

GH

ij

kl

MN

Op

Let us break flatMap up into 2 operations:

map:

[ [AB, CD, EF]      [GH, ij]           [kl, MN, op] ]

  Stream 1             Stream 2           Stream 3

flatten it:

AB, cd, EF             GH, ij               kl ,MN ,op

The flatMap() does a map + flat. Flattening here is of the individual streams from each item in the list to a single stream. The flatMap() methods needs a stream and hence the list->list.stream().The flatMap method takes an input and can give either 0 or more elements.

Let us consider another example to understand this well. Let us consider 3 different football leagues. The English Premier league, the LIGA BBVA or the Spanish League and the Bundesliga. Each league has a list of teams. We can represent this as:


public class League {
private String leagueName;
private List<Team> teams;
}

view raw

League.java

hosted with ❤ by GitHub


public class Team
{
private String name;
public Team(String teamName){
this.name=teamName;
}
}

view raw

Team.java

hosted with ❤ by GitHub

Problem: Given a list of leagues, we need to return the names of the all the teams in the leagues.

Imperative style:


private static List<String> displayAllTeamNamesImperative(List<League> leagues){
List<String> teamNames = new ArrayList<>();
for(League league : leagues)
{
List<Team> teams = league.getTeams();
for(Team team : teams)
{
teamNames.add(team.getName());
}
}
return teamNames;
}

Declarative style using map:

We have a list of leagues. When we call stream() on it, it will operate on a single League object. But a league has multiple teams in it.  If we try solving this using map() then we land up getting this:


leagues.stream()
.map(league -> league.getTeams().stream())
.forEach(System.out::println);

Output:

java.util.stream.ReferencePipeline$Head@87aac27

java.util.stream.ReferencePipeline$Head@3e3abc88

java.util.stream.ReferencePipeline$Head@6ce253f1

We land up getting 3 streams. This means that the map operation is not the right fit here. We need a function that can take these streams and combine each of these elements in these streams to a unified output.

This is the scenario for a flatMap() as we have a collection of collections. So the input is  a collection of leagues and each league has another collection which is team.


private static List<String> displayAllTeamNamesFunctional(List<League> leagues)
{
return leagues.stream()
.flatMap(league ->league.getTeams().stream())
.map( team ->team.getName())
.collect(Collectors.toList());
}

When you have a collection of collections and want a unified output, use the flatMap.

I hope you have understood the basics of both map and flatMap methods and the scenarios in which they should be applied.

 

Command Pattern using Java 8 Lambdas

I have been looking at how to improve my knowledge of Design Patterns and at the same time sharpen my Java 8 skills too. I have begun to realize that one can combine the two and also realized that Java 8 Lambdas are extremely powerful.

In this post, we are going to take a look at how the implementation of the Command Design Pattern can be simplified using Java 8 Lambdas.

I have written another blog where you can understand the essence of the Command Design Pattern.

The example we are going to refactor using Java 8 Lambdas is from here. This article on the tutorialspoint site refers to the typical way of implementing the pattern. You must take a look at it to get a basic understanding of the domain/problem at hand. The following is not a UML but I have shown the main components for the example mentioned.

 

CommandPatternWithoutClient

In short , BuyStock and SellStock are 2 commands which implement the Order interface. Stock is the recipient and finally the Broker is the invoker. The Broker class deals only with the Order interface and has no idea about the concrete commands.

Let us implement the same using Java 8 Lambdas. The Order interface is a Functional interface and each ConcreteCommand above is really a function. Do we really a class to represent each Command ? Well, take a look at the client code now using Lambdas:


public class CommandPatternDemo {
public static void main(String[] args) {
Stock abcStock = new Stock();
Broker broker = new Broker();
broker.takeOrder(() -> abcStock.buy());
broker.takeOrder(() -> abcStock.sell());
broker.placeOrders();
}
}

The Broker,Order interface remain the same and so does the Stock class. We can get rid of the individual Concrete Commands (BuyStock, SellStock) classes.

What we have done is actually passed behavior to the takeOrder method. This works as the Order interface has a method execute which takes no parameters and returns void. And hence () -> abcStock.buy() is a lambda expression which takes no parameters and returns void.

To understand this pattern better,  let us extend our problem. Imagine that in the same system, we had to sell Bonds too. The process of buying/selling stocks is different from bonds. With the Broker and the Order interface, the system can easily be extended with minimal changes.

NewCommandPattern

We added 2 more classes BuyBond and SellBond which implement the Order interface. These commands would invoke the Bond class( Receiver) which would perform the task of either buying or selling bonds. The Broker class remains untouched as it deals with only the Order Interface. Well, using Java 8 Lambdas, we don’t need the BuyBond or SellBond classes either.


//Client
public class CommandPatternDemo {
public static void main(String[] args) {
//Stock
Stock abcStock = new Stock();
Broker broker = new Broker();
broker.takeOrder(() -> abcStock.buy());
broker.takeOrder(() -> abcStock.sell());
//Bond
Bond bond = new Bond();
broker.takeOrder(() -> bond.buyBonds());
broker.takeOrder(() -> bond.sellBonds());
broker.placeOrders();
}
}

The Command pattern can be implemented easily using Lambdas. One could argue that the Order interface has just 1 method and we haven’t considered the undo and redo commands in the Command Design pattern. We can always fall back on the typical implementation of the pattern in case we need an undo and redo in addition to the execute functionality.

Having said that, do we always need an Order interface which acts as the Command interface ? How about using the Runnable interface instead  to run all the commands?  It could affect the readability of the code a little bit but otherwise the use of Java 8 Lambdas really makes the implementation easy and powerful at the same time.

Understanding the Command Design Pattern

Let us forget all design patterns for a moment and let us try to solve a simple problem using basic Java programming knowledge.

Problem: I would like to collect tasks to be executed later.

Let us break this down:

  1. The first part is collecting tasks –  this would mean using some kind of a storage which would add tasks together in a data structure. In Java, this can be done using  a Collection. So we need to maintain a Collection<Something>.
  2. Well a better idea would be a List<Something>. A List would be more specific.
  3. What is this Something ? It is a Task ! Okay,  a List<Task> ?
  4. That gives birth to a class Task, now we have a List<Task> to which we can add a task.
  5. Let us get more specific, let us begin with an ArrayList, this would be List<Task> tasks = new ArrayList<>()
  6. But this Task could be different types of tasks. Each “type” of Task… Each “type” of Task…List is generic, it is an interface,  ArrayList, LinkList are different “types” of List. So what next ?
  7. Refactor Task to an interface, and let each “type” of Task be a class which implements the interface Task.
  8. With this in place, we can add any type of Task to the tasks arraylist above. Task1,Task2….Taskn implements Task.
  9. As we are now done with collecting tasks, let us turn to the second part of running the tasks. The interface Task should have a method, let us call it executeTask(). Each type of Task will now override the executeTask() and perform it’s own task.
  10. To run each task – loop through each task and simply call the executeTask method.

for(Task task : tasks) {
task.executeTask();
}

In fact, the above for loop can be executed by using the Runnable interface/Thread class.

Let us turn our attention to the UML of actual Command Design Pattern :

 

Command_Pattern

Each type of Task is really a ConcreteCommand. The Command interface is really the same Task interface. The Invoker is a class which executes the for loop above and maintains a list of tasks/command. The only thing we have not seen is the Receiver, well when each Task/Command is executed, the Receiver will be invoked from each task. It is the work horse of the Command, the object that really does the work.

Advantages of using the Command Pattern:

  1. We can add ‘n’ different commands to the system later but the Invoker remains the same as it only deals with the Interface(Command/Task).
  2. Invoker is not aware of the work horse or the Receiver of each Command. So our system is extensible and loosely coupled.

This is really the essence of the Command Design Pattern.

I have written another blog where I dive into the implementation of the pattern.