Java 8 – Some of the new features

In this post, some of the new features of JAVA 8…

package pt.joaobrito.java8;

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.Month;
import java.time.Period;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

public class Main {

    public static void main(String[] args) throws InterruptedException {
        // simple lambda example
        print("Hello Lambda", s -> s.length());

        // another lambda example
        new Thread(() -> System.out.println("Hello Runnable")).start();

        List<Person> people = new ArrayList<>(Arrays.asList(
            new Person("John Doe", LocalDate.of(1978, Month.JUNE, 14)),
            new Person("Jane Doe", LocalDate.of(1983, Month.FEBRUARY, 16)),
            new Person("Steven Smith", LocalDate.of(2008, Month.SEPTEMBER, 23)),
            new Person("Martin", LocalDate.of(2010, Month.NOVEMBER, 27)),
            new Person("Mike", LocalDate.of(2012, Month.NOVEMBER, 3)),
            new Person("Louis", LocalDate.of(2014, Month.NOVEMBER, 6)),
            new Person("Mary", LocalDate.of(2016, Month.FEBRUARY, 16))
        ));

        System.out.println("---- All people sorted by name -----");
        people.sort((p1, p2) -> p1.getName().compareTo(p2.getName()));
        people.forEach(p -> System.out.println(p.getName()));

        System.out.println("---- All people -----");
        people = new ArrayList<>(Arrays.asList(
            new Person("John Doe", LocalDate.of(1978, Month.JUNE, 14)),
            new Person("Jane Doe", LocalDate.of(1983, Month.FEBRUARY, 16)),
            new Person("Steven Smith", LocalDate.of(2008, Month.SEPTEMBER, 23)),
            new Person("Martin", LocalDate.of(2010, Month.NOVEMBER, 27)),
            new Person("Mike", LocalDate.of(2012, Month.NOVEMBER, 3)),
            new Person("Louis", LocalDate.of(2014, Month.NOVEMBER, 6)),
            new Person("Mary", LocalDate.of(2016, Month.FEBRUARY, 16))
        ));
        people.stream().map(Person::getName).forEach(System.out::println); // using method reference

        System.out.println("---- People older than 9 yrs -----");
        people
            .stream() // convert to stream
            .filter(p -> Period.between(p.getDob(), LocalDate.now()).getYears() > 9) // get only the people thaht matches the given condition
            .map(Person::getName) // get a new stream with only the names => returns Stream<String>
            .forEach(System.out::println); // iterates the entire stream and prints out each element

        System.out.println("---- Remove items from list -----");
        people.removeIf(i -> i.getAge() < 2); // remove if the given condition is true
        people.
            stream()
            .map(Person::getName)
            .sorted(Comparator.reverseOrder()) // order the list in reverse order
            .forEach(System.out::println);

        // calculate time between two dates
        LocalDate dob = LocalDate.of(1978, 6, 14);
        LocalDate now = LocalDate.now();
        Period p = Period.between(dob, now);
        System.out.println("Priod of " + p.getYears() + " years; " + p.getMonths() + " months, " + p.getDays() + " days.");

        // calculate time between two instants
        Instant start = Instant.now();
        Thread.sleep(1000);
        Instant end = Instant.now();
        System.out.println("The time is... " + Duration.between(start, end).toMillis());

        // Optional<T>
        Optional<String> opt = Optional.ofNullable("some string"); // not null value
        System.out.println(opt.orElse("or else"));
        opt.orElseThrow(UnsupportedOperationException::new);

        opt = Optional.ofNullable(null); // notice that here we pass a null value
        System.out.println(opt.orElse("or else"));
        opt.orElseThrow(UnsupportedOperationException::new);

    }

    public static void print(String s, MyLambda l) {
        System.out.println(l.getLength(s));
    }

}

@FunctionalInterface
interface MyLambda {
    int getLength(String s);
}
package pt.joaobrito.java8;

import java.time.LocalDate;
import java.time.Period;

public class Person {
    private String name;
    private LocalDate dob;

    public Person(String name, LocalDate dob) {
        this.name = name;
        this.dob = dob;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public LocalDate getDob() {
        return dob;
    }

    public void setDob(LocalDate dob) {
        this.dob = dob;
    }
    
    public int getAge(){
        return Period.between(dob, LocalDate.now()).getYears();
    }
}

 

…and here are the results from running the file above

------------------------------------------------------------------------
Building Java8 0.0.1-SNAPSHOT
------------------------------------------------------------------------

--- exec-maven-plugin:1.2.1:exec (default-cli) @ Java8 ---
12
Hello Runnable
---- All people sorted by name -----
Jane Doe
John Doe
Louis
Martin
Mary
Mike
Steven Smith
---- All people -----
John Doe
Jane Doe
Steven Smith
Martin
Mike
Louis
Mary
---- People older than 9 yrs -----
John Doe
Jane Doe
---- Remove items from list -----
Steven Smith
Mike
Mary
Martin
Louis
John Doe
Jane Doe
Priod of 39 years; 9 months, 9 days.
The time is... 1014
some string
or else
Exception in thread "main" java.lang.UnsupportedOperationException
	at java.util.Optional.orElseThrow(Optional.java:290)
	at pt.joaobrito.java8.Main.main(Main.java:83)
------------------------------------------------------------------------
BUILD FAILURE
------------------------------------------------------------------------
Total time: 1.649 s
Finished at: 2018-03-23T00:07:33+00:00
Final Memory: 8M/309M
------------------------------------------------------------------------

Note that the build fails because we pass null to the Optional and we have a condition to throw an exception if null is passed to it (this is the reason why this line is the last statement of this example).

Thank you! 🙂

 

Design Pattern: Command and State together

In this article we will explain two JAVA design patterns:
Command and State.

In the main method we:

  1. first create the light object (aka receiver);
  2. then we check if the light is on or off;
  3. after that we create a light command passing to it the light we’ve just created;
  4. then we create a Remote Control and set the command into it;
  5. in the next step we press the button and we check the light state;
  6. finally, we repeat the process and check the light state again.

So lets start with the  code:

Here we have the client class (the one that have the main method)

package pt.joaobrito.client;

import pt.joaobrito.command.Command;
import pt.joaobrito.command.LightCommand;
import pt.joaobrito.command.invoker.RemoteControl;
import pt.joaobrito.state.receiver.Light;

/**
 * The client object 
 */
public class Client {

    public static void main(String[] args) {
        // receiver
        Light light = new Light();
        
        // prints to the console the current state of the light
        System.out.println("1st state - the light is " + (light.getCurrentState().isOn() ? "ON" : "OFF"));
        
        Command lightsCmd = new LightCommand(light);
        
        //invoker
        RemoteControl remoteControl = new RemoteControl();
        remoteControl.setCommand(lightsCmd);
        
        //switch on
        remoteControl.pressButton();
        System.out.println("2nd state - the light is " + (light.getCurrentState().isOn() ? "ON" : "OFF"));
        
        //switch off
        remoteControl.pressButton();
        System.out.println("3rd state - the light is " + (light.getCurrentState().isOn() ? "ON" : "OFF"));
    }
}

 

The Command Design Pattern implementation
Here we define our Command interface

package pt.joaobrito.command;

public interface Command {
    public void execute();
}

 

This is the remote control class.
Note that in the pressButton method we actually execute the Command passed previously in the set method. Notice that this class has no knowledge at all about the receiver. Instead it just knows that it has a Command and how to interact with it.

package pt.joaobrito.command.invoker;

import pt.joaobrito.command.Command;

/**
 * Invoker
 */
public class RemoteControl {

    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}

 

Here we have the concrete  light command (the implementation of the Command interface). In the execute method we specify what the command really does: in this case with the help of the State Design Pattern we are simply saying to the light to go to the next state.

package pt.joaobrito.command;

import pt.joaobrito.state.receiver.Light;

/**
 * Concrete Command: light command
 */
public class LightCommand implements Command {
    //reference to the light
    private Light light;

    public LightCommand(Light light) {
        this.light = light;
    }

    public void execute() {
        light.switchToNextState();
    }
}

 

The next section is the State Design Pattern part
This is the Light class. From the Command point of view this is the receiver and from the point of view of the state design pattern this is the object that keeps the current state of the light (also known as a wrapper that will be passed to the concrete states).

package pt.joaobrito.state.receiver;

/**
 * This class is responsible to keep the state of the light
 */
public class Light {
    private State currentState;
    
    public Light() {
        // 1st state of light
        currentState = new LightOff();
    }

    public State getCurrentState() {
        return currentState;
    }

    public void setState(State state) {
        currentState = state;
    }

    /**
     * light switch
     */
    public void switchToNextState() {
        currentState.next(this);
    }

}

 

This is the state interface. Notice that here we have two methods that have to be implemented by the classes that implement the state interface.

package pt.joaobrito.state.receiver;

public interface State {
    void next(Light wrapper);
    boolean isOn();
}

 

The next class represents one of the possible state of the light (the concrete state that represents the ON state of the light)

package pt.joaobrito.state.receiver;

/**
 * Receiver
 */
public class LightOn implements State{
    
    @Override
    public void next(Light wrapper) {
        wrapper.setState(new LightOff());
    }

    @Override
    public boolean isOn() {
        return true;
    }
}

 

This is the other possible state (the concrete state that represents the OFF state of the light)

package pt.joaobrito.state.receiver;

/**
 * Receiver
 */
public class LightOff implements State{

    @Override
    public void next(Light wrapper) {
        wrapper.setState(new LightOn());
    }

    @Override
    public boolean isOn() {
        return false;
    }
}

 

And the results:

run:
1st state - the light is OFF
2nd state - the light is ON
3rd state - the light is OFF
BUILD SUCCESSFUL (total time: 0 seconds)

 

And that’s it. Feel free to comment.

Thank you!