Java 9: Immutable List, Set and Map

Java 9  provides a convenient way to create an immutable collections such as List, Set and Map. In this post, we are going to see that with few examples.

Prior to Java 9, To create an immutable collections, we have to follow the below approach. It works fine but its verbose.

ImmutableJava8

Now, in Java 9, we can easily, create an immutable list with the List.of() method.

The List.of method returns an instance of “java.util.ImmutableCollections.ListN” [extends AbstractImmutableList]. As this class extends AbstractImmutableList, the returned list is an immutable list, so trying to update it, will throw UnsupportedOperationException.

ImmutableList.JPG

We can follow the same way for creating an immutable Set and Map. Refer the below examples.

The Set.of method returns an instance of “java.util.ImmutableCollections.SetN” [extends AbstractImmutableSet]. Its immutable so trying to update it, will throw UnsupportedOperationException.

The Map.of method returns an instance of “java.util.ImmutableCollections.MapN” [extends AbstractImmutableMap]. Its immutable so trying to update it, will throw UnsupportedOperationException.

ImmutableSet.JPG

ImmutableMap.JPG

BiConsumer Interface – Example

BiConsumer is a functional interface which represents an operation that accepts two input arguments and returns no result.

Lets see how we can use BiConsumer interface with an example.


import java.util.function.BiConsumer;

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

        BiConsumer addConsumer = (x, y) -> {
            System.out.println("Add Operation result:" + (x+y));
        };

        BiConsumer subtractConsumer = (x, y) -> {
            System.out.println("Subtract Operation result:" + (x - y));
        };

        BiConsumer divideConsumer = (x, y) -> {
            System.out.println("Divide Operation result:" + (x / y));
        };

        BiConsumer multiplyConsumer = (x, y) -> {
            System.out.println("Multiply Operation result:" + (x * y));
        };
        addConsumer
            .andThen(subtractConsumer)
            .andThen(divideConsumer)
            .andThen(multiplyConsumer)
            .accept(10, 5);
    }

}

In the above program, we have defined 4 BiConsumer operations and each one takes two integer values as input and perform appropriate arithmetic operation and prints the result.

We can chain all these operations with andThen() method.

The output of the above program is given below.



Add Operation result:15
Subtract Operation result:5
Divide Operation result:2
Multiply Operation result:50


If an error occurs in any one of the operation, then the next operation would not be executed. For example, if you pass 10, 0 then java.lang.ArithmeticException would happen in the divide operation so it will not execute the multiply operation.

Refer below the code and its response.


import java.util.function.BiConsumer;

public class BiConsumerExample {

    public static void main(String[] args) {

        BiConsumer addConsumer = (x, y) -> {
            System.out.println("Add Operation result:" + (x+y));
        };

        BiConsumer subtractConsumer = (x, y) -> {
            System.out.println("Subtract Operation result:" + (x - y));
        };

        BiConsumer divideConsumer = (x, y) -> {
            System.out.println("Divide Operation result:" + (x / y));
        };

        BiConsumer multiplyConsumer = (x, y) -> {
            System.out.println("Multiply Operation result:" + (x * y));
        };
        addConsumer
            .andThen(subtractConsumer)
            .andThen(divideConsumer)
            .andThen(multiplyConsumer)
            .accept(10, 0);
    }

}



Add Operation result:10
Subtract Operation result:10
Exception in thread "main" java.lang.ArithmeticException: / by zero


IterableUtils – Example

In this post, we are going to see how we can use IterableUtils of Apache commons collections with an example.

Assume that you want to retrieve a key value from environmental variables. If its not available, then we would need to get it from system properties. If its not available even there, then we would need to assume a default value.

We can easily do it with an if else. But with the use of IterableUtils, we can avoid those boiler plate code.

Refer the below code.


import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.collections4.functors.NotNullPredicate;

import java.util.Arrays;

public class IterableMain {

    public static void main(String[] args) {
        //Get the default value
        System.out.println("Uses default app name:" + getKeyValue("APP_NAME", "Default App Name"));
        //Get the key value from system properties
        System.setProperty("APP_NAME", "App Name1");
        System.out.println("Uses system property app name:" + getKeyValue("APP_NAME", "Default App Name"));
    }

    private static String getKeyValue(String key, String defaultValue) {
        String envKey = System.getenv(key);
        String propKey = System.getProperty(key);
        return IterableUtils.find(Arrays.asList(envKey, propKey, defaultValue), NotNullPredicate.notNullPredicate());
    }

}

In the above code, we first retrieve the key value from environmental variables and also from system properties and create a list contains the envKeyValue, propKeyValue and also a default value. We have to keep the order as is.

Then we use IterableUtils and invoke find method and pass that list and the Not Null predicate. Hence the first not null value would be returned as an output.

** If the key presents in environmental variable then environment value would be returned.

** If the key is not there in environmental variable but present in system properties, then the list looks like this (null, “App Name1”, “Default App Name”). So the first not null value would be returned as an output. So “App Name1” is the output.

** If none of the values exist, then the list looks like this (null, null, “Default App Name”). So the default app name would be returned.

The output of the above program is given below,


Uses default app name:Default App Name
Uses system property app name:App Name1


Wilson’s Theorem to find prime number

Wilson’s Theorem states that a natural number is p > 1 is a prime number if only if the below condition is met.


  (p - 1) ! ≡  -1   mod p 
 OR  (p - 1) ! ≡  (p-1) mod p

For example, Take p as 4
(4 – 1)! = 3 ! => 3 * 2 * 1 = 6
(6 % 4) != 3 => 6 not equals to 3
So p is not a prime number.

Take p as 5
(5-1)! = 4 ! => 4*3*2*1 = 24
24%5 == 4
4 == 4
So p is a prime number.

Refer the below code to know how to do with a java program.


import java.util.Scanner;

public class PrimeFInder {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        int number = scanner.nextInt();
        System.out.println("The entered number is "+number);

        //  (p - 1) ! ≡  (p-1) mod p
        int lhs = getFactorialValue(number- 1) % number;
        int rhs = number - 1;
        if(lhs == rhs){
            System.out.println("Its a prime number");
        }else{
           System.out.println("Its an non prime number");
        }
    }

    private static int getFactorialValue(int n) {
        int value = 1;
        for (int i = 1; i <= n; i++) {
            value *= i;
        }
        return value;
    }
}

The output is given below,


12
The entered number is 12
Its an non prime number


Unroll annotation in Spock Testing framework

Spock is a testing framework for Java and Groovy application. This is a best alternative to Junit. In this post, Let’s see how we can use Unroll annotation of spock framework with an example.

Let’s assume that we have a class called “MathOperation” contains methods to perform arithmetic operations and we have a spock test class to test those methods.

MathOperation.java


public class MathOperation {
    
    private MathOperation(){
        
    }

    public static int sum(int a, int b) {
        return a + b;
    }

    public static int divide(int a, int b) {
        return a / b;
    }

    public static int multiply(int a, int b) {
        return a * b;
    }

    public static int minus(int a, int b) {
        return a - b;
    }
}


The spock test for testing the ‘sum’ method is as below.


import spock.lang.Specification

class MathOperationSpec extends Specification {

    def "sum of two numbers"() {

        expect:
        int actual = MathOperation.sum(num1, num2);
        actual == expected

        where:

        num1 | num2 | expected
        1    | 2    | 3
        2    | 3    | 5
    }

When we run this test case, the test run will look like below,

spock-withouunroll

When an error happened, we are not sure which line caused the problem. It will report only the error method but would not give the information about the exact line. The Unroll annotation helps to fix this problem. Unroll annotation has no effect on how the method gets executed but its an alternation in reporting.

Lets rewrite the above test with Unroll annotation as below.


import spock.lang.Specification
import spock.lang.Unroll

class MathOperationSpec extends Specification {

    @Unroll
    def "sum of two numbers #num1 #num2"() {

        expect:
        int actual = MathOperation.sum(num1, num2);
        actual == expected

        where:

        num1 | num2 | expected
        1    | 2    | 3
        2    | 3    | 5
    }
}

When we run the above one, it will look like below,
spock-withunroll

Java 8: Stream sorted

In this post, we are going to see how we can use Stream.sorted method to sort a collection with an example.

Consider that we have Person class contains “name” and “age” fields and want to sort the list of person objects by age and then by name.

Refer the below code to know how to do that.


import com.google.common.collect.Lists;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class CollectionMain {

    static class Person {
        String name;
        Integer age;

        Person(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return new ToStringBuilder(this, ToStringStyle.SIMPLE_STYLE)
                .append("name", name)
                .append("age", age)
                .toString();
        }

        public String getName() {
            return name;
        }


        public Integer getAge() {
            return age;
        }

    }

    private static final Comparator PERSON_COMPARATOR = Comparator.comparing(Person::getAge).thenComparing(Person::getName);

    public static void main(String[] args) {
        List persons = Lists.newArrayList(new Person("John", 32),
            new Person("Tom", 33),
            new Person("Brad", 35),
            new Person("Varma", 38),
            new Person("Andy", 33));

        System.out.println(persons
            .stream()
            .filter(p -> p.age > 32)
            .sorted(PERSON_COMPARATOR)
            .collect(Collectors.toList()));

    }
}



[Andy,33, Tom,33, Brad,35, Varma,38]

Java: Stream.Reduce

In this post, we are going to see how we can use Stream reduce operation on a list with an example.

Stream.Reduce()

Stream.Reduce() is a general purpose reduction operation. We can use this operation to process a list and find out the max, min and average value. It’s like applying to a list of values and get a single result value.

The syntax is given below


T reduce(T identity, BinaryOperator accumulator)

Here identity is the initial value and accumulator is a function for combining values.

reduce

In the above example, I have a list of string and want to find out the long string in it. I have used reduce operation to find it out.

Let’s see another example. Assume that we want to process a list and modify the value of it and then reduce the value into a single value. Refer the below example to know how we can achieve this with reduce operation.

reduce-modify-list