Functional programming with Java - Part 1

 Recently I was reviewing one PR raised by team memeber and going through one utitlity method and found out there are too many muatable variable roaming aroung in the code which I didn't like, So thought to convert in Funtional way,



import java.net.Inet6Address;

import java.net.InetAddress;

import java.net.InterfaceAddress;

import java.net.NetworkInterface;

import java.util.Enumeration;


public class MultipleIPAddressCal {

    private MultipleIPAddressCal() {}

    public static String getAllIpAddresses() {

        StringBuilder allIPAddress = new StringBuilder();

        String allIPAddressAppended = null;

        try{

            Enumeration<networkinterface> interfaces = NetworkInterface.getNetworkInterfaces();

            while (interfaces.hasMoreElements()) {

                NetworkInterface networkInterface = interfaces.nextElement();

                if (!networkInterface.isUp()) {

                    continue;

                }

                for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {

                    int npf = interfaceAddress.getNetworkPrefixLength();

                    InetAddress address = interfaceAddress.getAddress();

                    allIPAddress.append(address.getHostAddress()).append(";");

                }

            }

            int lastSemiColon = allIPAddress.lastIndexOf(";");

            allIPAddressAppended = allIPAddress.substring(0,lastSemiColon);

        } catch (Exception ex){

            log.error(ex.getMessage());

        }

        return allIPAddressAppended;

    }

}


Let's convert this code to functional way So it will be less cluttered.


import org.apache.commons.lang3.StringUtils;


import java.net.InetAddress;

import java.net.InterfaceAddress;

import java.net.NetworkInterface;

import java.util.Enumeration;

import java.util.Spliterator;

import java.util.stream.Collectors;

import java.util.stream.StreamSupport;


public class MultipleIPAddressCal {

    private MultipleIPAddressCal() {

    }


    public static String getAllIpAddresses() {

        try {

            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

            EnumerationSpliterator<NetworkInterface> spliterator

                    = new EnumerationSpliterator<NetworkInterface>(Long.MAX_VALUE, Spliterator.ORDERED, interfaces);

            return StreamSupport.stream(spliterator, false)

                    .flatMap(networkInterface -> networkInterface.getInterfaceAddresses()

                            .stream()

                            .map(MultipleIPAddressCal::extractIPV6address))

                            .collect(Collectors.joining(";"));

        } catch (Exception ex) {

            log.error(ex.getMessage());

            return StringUtils.EMPTY;

        }

    }


    private static String extractIPV6address(InterfaceAddress interfaceAddress) {

        InetAddress address = interfaceAddress.getAddress();

        if (address.getHostAddress().lastIndexOf("%") != -1) {

            return address.getHostAddress().substring(0, address.getHostAddress().lastIndexOf("%"));

        } else {

            return address.getHostAddress();

        }

    }

}


To convert Enumeration into stream you need SplitIterator on it.

import java.util.Enumeration;

import java.util.Spliterators;

import java.util.function.Consumer;

public class EnumerationSpliterator<T> extends Spliterators.AbstractSpliterator<T> {

    private final Enumeration<T> enumeration;

    public EnumerationSpliterator(long est, int additionalCharacteristics, Enumeration<T> enumeration) {

        super(est, additionalCharacteristics);

        this.enumeration = enumeration;

    }

    @Override

    public boolean tryAdvance(Consumer<? super T> action) {

        if (enumeration.hasMoreElements()) {

            action.accept(enumeration.nextElement());

            return true;

        }

        return false;

    }

    @Override

    public void forEachRemaining(Consumer<? super T> action) {

        while (enumeration.hasMoreElements())

            action.accept(enumeration.nextElement());

    }

}


Happy Coding!!

Modify a stack such a way that it should return smallest element in O(1) complexity

import java.util.Stack;

public class MinimumFromStack {
    public static void main(String[] args) {
        Stack<Pair> stack = new Stack<>();
        Pair pair = new Pair(5,stack);
        stack.add(pair);
        Pair pair1 = new Pair(9,stack);
        stack.add(pair1);
        Pair pair2 = new Pair(7,stack);
        stack.add(pair2);
        Pair pair3 = new Pair(6,stack);
        stack.add(pair3);
        Pair pair4 = new Pair(3,stack);
        stack.add(pair4);
        
        
        System.out.println("Smallest element in stack : " + stack.peek().getMinimum());
        System.out.println("Top element in stack : " + stack.peek().getActual());
        System.out.println("removing Top element in stack : " + stack.pop());
        System.out.println("Smallest element in stack : " + stack.peek().getMinimum());
    }
    
    private static class Pair {
        int actual;
        int minimum;
        
        Pair(int actual,Stack<Pair> stack){
            this.actual =actual;
            this.minimum = stack.isEmpty() ? actual : Math.min(actual,stack.peek().getMinimum());
        }
        
        public int getActual() {
            return actual;
        }
        
        public int getMinimum() {
            return minimum;
        }

    }
}

Producer Consumer Problem Reentrant Lock

public class ProducerConsumerProblem {

public static void main(String[] args) throws InterruptedException {
Lock lock = new ReentrantLock();
List<Integer> buffer = new LinkedList<>();
Condition isEmpty = lock.newCondition();
Condition isFull = lock.newCondition();

ExecutorService executorService = Executors.newFixedThreadPool(2);
List<Callable<String>> list = new ArrayList<>();
list.add(new Producer(lock, buffer, isEmpty, isFull));
list.add(new Consumer(lock, buffer, isEmpty, isFull));
final List<Future<String>> futures = executorService.invokeAll(list);

futures.forEach(stringFuture -> {
try {
System.out.println("Done :" + stringFuture.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
System.out.println("ExecutorService Shutdown");
}
});
}

private static class Producer implements Callable<String> {
private Lock producerLock;
private List<Integer> buffer;
Condition isEmpty;
Condition isFull;

Producer(Lock lock, List<Integer> buffer, Condition isEmpty, Condition isFull) {
this.producerLock = lock;
this.buffer = buffer;
this.isEmpty = isEmpty;
this.isFull = isFull;
}


@Override
public String call() throws Exception {
int count = 1;
for (; count <= 50; count++) {
try {
producerLock.lock();
if (buffer.size() == 50) {
isFull.await();
}
buffer.add(1);
isEmpty.signalAll();
} finally {
producerLock.unlock();
}

}
return "Produced : " + (count - 1);
}
}

private static class Consumer implements Callable<String> {

private Lock consumerLock;
private List<Integer> buffer;
Condition isEmpty;
Condition isFull;

Consumer(Lock lock, List<Integer> buffer, Condition isEmpty, Condition isFull) {
this.consumerLock = lock;
this.buffer = buffer;
this.isEmpty = isEmpty;
this.isFull = isFull;
}


@Override
public String call() throws Exception {
int count = 1;
for (; count <= 50; count++) {

try {
consumerLock.lock();
if (buffer.isEmpty()) {
isEmpty.await();
}
buffer.remove(buffer.size() - 1);
isFull.signalAll();
} finally {
consumerLock.unlock();
}
}
return "Consumed : " + (count - 1);
}
}

}

Include conditional dependencies and packages in gradle

I got a task in my project to add some dependencies on need basis.

We are creating a jar for different tools, lots of code we have common but some of code and dependencies required for jar is not needed for other.

Before directly jumping into actual code base I wanted get my hand dirty in some dummy project, So I have spent some time to understands gradle tasks and dependency management and created the dummy project.

I am rewriting here for my own benefit and yours as well.

We can add dependencies by providing build time argument

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    if(project.property("build").equals("build1")){
        println "Including dependencies of build1"
        compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.0'
    }
    if (project.property("build").equals("build2")){
        println "Including dependencies of  build2"
        compile group: 'com.google.code.gson', name: 'gson', version: '2.7'
    }
}


To add the conditional dependency we need to run our build command
gradle build -Pbuild="build1"
Or
gradle build -Pbuild="build2"


We can create the separate task for separate Jars.

Task build the Jar for Build1:-
task build1Jar(type: Jar){
    from sourceSets.main.output

    exclude '**/package2/**'

    manifest {
        attributes(
                "Manifest-Version": "1.0",
                "Main-Class" : "com.ravat.package1.Runner",
                "Class-Path":  configurations.runtimeClasspath.collect { it.getName() }.join(' ')
        )
    }
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
    baseName = 'build1'
}

Task build the Jar for Build2:-
task build2Jar(type: Jar){
    from sourceSets.main.output

    exclude '**/package1/**'

    manifest {
        attributes(
                "Manifest-Version": "1.0",
                "Main-Class" : "com.ravat.package2.Runner",
                "Class-Path":  configurations.runtimeClasspath.collect { it.getName() }.join(' ')
        )
    }
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
    baseName = 'build2'
}

To create a jar with required dependencies and package we need to run the following gradle command
gradle clean install build1Jar
or
gradle clean install build2Jar 

Magic of bit manipulation : fastest way to swap two variables

We all have faced this question in our interview process to swap 2 variables.

If not faces while working with arrays we may have faced to swap 2 variables in array.

I hope, you all know the concept of swapping 2 variables. today I am going to show you the fastest way to swap two variables.

We all know data is stored in computer memory in the form of bits(0 & 1), that means all the operation we do on the bits will be perform faster by computer.

some bit manipulation examples :-

Bitwise XOR operator :-

value  ^ 0s         ==   value 
value  ^ 1s         ==  ~value
value  ^ value      ==   0s

Bitwise AND Operator :-

value  &  0s      ==  0s 
value  &  1s      ==  value
value  &  value   ==  value

Bitwise OR Operator :-

value  |  0s       ==  value 
value  |  1s       ==  1s
value  |  value    ==  value

We will use XOR Operator to swap 2 variable :-

x = 10
y = 12

8 4 2 1
1 0 1 0  = 10(x)
1 1 0 0  = 12(y)

x = x ^ y  1010^1100 = 0110
y = x ^ y  0110^1100 = 1010 (10)
x = x ^ y  0110^1010 = 1100 (12)

We will implement a bubble sort algorithm to see the benefit of bit manipulation:-

import java.util.Arrays;

public class BubbleSort {
    public static void main(String[] args) {
        int[] array = new int[]{20,35,-15,7,55,1,-22};
        array = bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }

    private static int[] bubbleSort(int[] array) {
        for (int i=0;i<array.length;i++){                       
            for (int j=0;j < array.length-i-1;j++) {             
                if (array[j] > array[j+1]){                       
                    //fastest way to swap two variable
                    array[j] = array[j] ^ array[j+1];
                    array[j+1] = array[j] ^ array [j+1];
                    array[j] = array[j] ^array[j+1];
                }
            }
        }
        return array;
    }
}

Functional programming with Java - Part 1

 Recently I was reviewing one PR raised by team memeber and going through one utitlity method and found out there are too many muatable vari...