December 23, 2018

How to use or implement test and negate methods in java.util.function.BiPredicate in java

We have Functional Interfaces in java, which returns a boolean-value after operating on it’s inputs.

BiPredicate is one of those Functional interfaces, which returns a boolean value.

It has four functions in it’s definition. Three of them are default and one is abstract and it is called test.

  1. boolean test( T input1, U input2) :- It returns a boolean value, which can be either false or true.
  2. default BiPredicate<T, U> negate() :- It returns a BiPredicate. This BiPredicate is logically opposite of the BiPredicate, which calls the negate function.
  3. default BiPredicate<T, U> or(Bipredicate<? super T, ? super U> other ) :- It creates a composed BiPredicate, which is basically a short-circutting logical-or operation.
  4. default BiPredicate<T, U> and(BiPredicate<? super T, ? super U> other) :- It creates a composed BiPredicate, which is basically a short-circutting logical-and operation.

We will go through the test and negate function only, in this article. You can read about logical and – or functions here.

In this article, we will implement a very common operation i.e to check greater or smaller between two integers.

We will be using these two local variables in our program.

final int smallerInt = 100;                                                                                                                                                                         
final int biggerInt = 101;

Let us provide a imperative implementation for greater and smaller operations.

private static boolean isSmaller(final int first, final int second) {                                                                                                                                   
    return first < second;                                                                                                                                                                              
}                                                                                                                                                                                                       
                                                                                                                                                                                                            
private static boolean isGreater(final int first, final int second) {                                                                                                                                   
    return first > second;                                                                                                                                                                              
}

The above two examples doesn’t look that imperative. Let me give an implementation which uses if-statement, to make it really look like imperative, let us add if-statements.

private static boolean isSmaller_WithIfElse(final int first, final int second) {                                                                                                                               
    if(first < second) {                                                                                                                                                                                       
        return true;                                                                                                                                                                                           
    }                                                                                                                                                                                                                                                                                                                                                                                                                         
    return false;                                                                                                                                                                                              
}                                                                                                                                                                                                              
                                                                                                                                                                                                                   
private static boolean isGreater_WithIfElse(final int first, final int second) {                                                                                                                               
    if(first > second) {                                                                                                                                                                                       
         return true;
    }                                                                                                                                                                                                                                                                                                                                                                                                                         
    return false;                                                                                                                                                                                              
}

So, above two statements are the same at operation level. But, we are providing independent implementations for isGreater and isSmaller. We really don’t need to do that.Because, isSmaller and isGreater are just opposite of each other. We can define one in respect of the other.

Let us implement isGreater in terms of isSmaller function.

private static boolean isGreater_UsingIsSmaller(final int first, final int second) {                                                                                                                           
    return ! (isSmaller(first, second));
}

Now, isGreater function just calls isSmaller function and returns the opposite of the value – returned by isSmaller function.

Now, moving to the functional implementaion using BiPredicate.

Implementation for isSmaller function.

final BiPredicate<Integer, Integer> isSmaller = (Integer first, Integer second) -> first < second;
final  BiPredicate<Integer, Integer> smallerUsingCompareTo = (Integer first, Integer second) -> first.compareTo(second) < 0;

Implementation for isGreater function.

final BiPredicate<Integer, Integer> isGreater = (Integer first, Integer second) -> first > second;

So, this is our independent implementation for isSmaller and isGreater, in functional way of programming, using java lambda.

As, these are independent implementations, let us implement the isGreater in terms of isSmaller.

It is very easy and code size is very small, because of negate function.

final BiPredicate<Integer, Integer> greaterUsingNegateMethod = isSmaller.negate();

See, we just needed to call one function i.e negate.

Q :- How can we do this negate operation in the imperative world, without using functional style.

It’s simple, we provide our own negate function.

private static boolean negate(boolean booleanValue) {                                                                                                                                                          
        return ! booleanValue;
}

That’s all we need to do inside the negate function.

Now, we can implement isGreater function using negate.

private static boolean isGreater_UsingIsSmaller_AndNegate(final int first, final int second) {                                                                                                                 
   return negate(isSmaller(first, second));
}

Q :- Do we need to re-implement all the imperative codes again to use this BiPredicate interface?

The answer is NO, you don’t need to re-implement all the functions again.

We can use java method referencing to do that.

Look in the below examples. We are using imperative method implementation to achieve this.

final BiPredicate<Integer, Integer> isSmaller_UsingImperativeSmaller = BiPredicate_TestAndNegate::isSmaller;
final BiPredicate<Integer, Integer> isGreater_UsingImperativeGreater = BiPredicate_TestAndNegate::isGreater;

The thing is, we can reuse our old code in new way.

Complete Code 

import java.util.function.BiPredicate;                                                                                                                                                                                                                                                                                       
import static java.lang.System.out;                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                             
public class BiPredicate_TestAndNegate {                                                                                                                                                                                                                                                                                     
    public static void main(String ... args) {                                                                                                                                                                                                                                                                               
        final int smallerInt = 100;                                                                                                                                                                                                                                                                                          
        final int biggerInt = 101;                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                             
        //Imperative Style                                                                                                                                                                                                                                                                                                   
        print("100 is smaller than 101 - ", isSmaller(100, 101));                                                                                                                                                                                                                                                            
        print("100 is greater than 101 [isGreater_UsingIsSmaller] - " , isGreater_UsingIsSmaller(100, 101));                                                                                                                                                                                                                 
        print("100 is greater than 101 [isGreater_UsingIsSmaller_AndNegate - ", isGreater_UsingIsSmaller_AndNegate(100, 101));                                                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                             
        //Functional Style                                                                                                                                                                                                                                                                                                   
        final BiPredicate<Integer, Integer> isSmaller = (Integer first, Integer second) -> first < second;                                                                                                                                                                                                                   
        final  BiPredicate<Integer, Integer> smallerUsingCompareTo = (Integer first, Integer second) -> first.compareTo(second) < 0;                                                                                                                                                                                         
                                                                                                                                                                                                                                                                                                                             
        final BiPredicate<Integer, Integer> isGreater = (Integer first, Integer second) -> first > second;                                                                                                                                                                                                                   
        final BiPredicate<Integer, Integer> greaterUsingNegateMethod = isSmaller.negate();                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                             
        print("100 is smaller than 101 [isSmaller] - ", isSmaller.test(100, 101));                                                                                                                                                                                                                                           
        print("100 is smaller than 101 [smallerUsingCompareTo] - ", smallerUsingCompareTo.test(100, 101));                                                                                                                                                                                                                   
        print("100 is greater that 101 [greaterUsingNegateMethod] - ", greaterUsingNegateMethod.test(100,101));                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                             
        //defining the smaller and greater method in terms of imperative functions                                                                                                                                                                                                                                           
        final BiPredicate<Integer, Integer> isSmaller_UsingImperativeSmaller = BiPredicate_TestAndNegate::isSmaller;
        final BiPredicate<Integer, Integer> isGreater_UsingImperativeGreater = BiPredicate_TestAndNegate::isGreater;
                                                                                                                                                                                
        out.println("100 is smaller than 101 [isSmaller_UsingImperativeSmaller] :- " + isSmaller_UsingImperativeSmaller.test(smallerInt, biggerInt));                                                                                                                                                                        
        out.println("100 is greater than 101 [isGreater_UsingImperativeGreater] " + isGreater_UsingImperativeGreater.test(smallerInt, biggerInt));                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                             
    }                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                             
    private static boolean isSmaller_WithIfElse(final int first, final int second) {                                                                                                                                                                                                                                         
        if(first < second) {                                                                                                                                                                                                                                                                                                 
            return true;                                                                                                                                                                                                                                                                                                     
        }                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                             
        return false;                                                                                                                                                                                                                                                                                                        
    }                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                             
    private static boolean isGreater_WithIfElse(final int first, final int second) {                                                                                                                                                                                                                                         
        if(first > second) {                                                                                                                                                                                                                                                                                                 
            return true;                                                                                                                                                                                                                                                                                                     
        }                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                             
        return false;                                                                                                                                                                                                                                                                                                        
    }                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                             
    private static boolean isSmaller(final int first, final int second) {                                                                                                                                                                                                                                                    
        return first < second;                                                                                                                                                                                                                                                                                               
    }                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                             
    private static boolean isGreater(final int first, final int second) {                                                                                                                                                                                                                                                    
        return first > second;                                                                                                                                                                                                                                                                                               
    }                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                             
    private static boolean isGreater_UsingIsSmaller(final int first, final int second) {                                                                                                                                                                                                                                     
        return ! (isSmaller(first, second));                                                                                                                                                                                                                                                                                 
    }                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                             
    private static boolean negate(boolean booleanValue) {                                                                                                                                                                                                                                                                    
        return ! booleanValue;                                                                                                                                                                                                                                                                                               
    }                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                             
    private static boolean isGreater_UsingIsSmaller_AndNegate(final int first, final int second) {                                                                                                                                                                                                                           
        return negate(isSmaller(first, second));                                                                                                                                                                                                                                                                             
    }                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                             
                                                                                                                                                                                                                                                                                                                             
    private static void print(final String message, final boolean booleanValue) {                                                                                                                                                                                                                                            
        out.println(message + booleanValue);                                                                                                                                                                                                                                                                                 
    }                                                                                                                                                                                                                                                                                                                        
}

Output :-

100 is smaller than 101 - true                                                                                                                                                                                     
100 is greater than 101 [isGreater_UsingIsSmaller] - false                                                                                                                                                         
100 is greater than 101 [isGreater_UsingIsSmaller_AndNegate - false                                                                                                                                                
100 is smaller than 101 [isSmaller] - true                                                                                                                                                                         
100 is smaller than 101 [smallerUsingCompareTo] - true                                                                                                                                                             
100 is greater that 101 [greaterUsingNegateMethod] - false                                                                                                                                                         
100 is smaller than 101 [isSmaller_UsingImperativeSmaller] :- true                                                                                                                                                 
100 is greater than 101 [isGreater_UsingImperativeGreater] false