Recent Posts

Thursday, 8 November 2018

Primitive Type Functional Interfaces

What is the Need of Primitive Type Functional Interfaces?
1. Autoboxing:
     Automatic conversion from primitive type to Object type by compiler is called autoboxing.
2. Autounboxing:
     Automatic conversion from object type to primitive type by compiler is called autounboxing.
     In the case of generics, the type parameter is always object type and no chance of passing primitive type.
ArrayList<Integer> l = new ArrayList<Integer>();//valid 
ArrayList<int> l = new ArrayList<int>();//invalid
Need of Primitive Functional Interfaces
     In the case of normal Functional interfaces (like Predicate, Function etc) input and return types are always Object types. If we pass primitive values then these primitive values will be converted to Object type (Auboxing), which creates performance problems.
import java.util.function.Predicate;
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      int[] x ={0,5,10,15,20,25};
      Predicate<Integer> p=i->i%2==0;
      for (int x1 : x) {
         if(p.test(x1)) {
            System.out.println(x1);
         }
      }
   }
}
     In the above examples,6 times autoboxing and autounboxing happening which creates Performance problems. To overcome this problem primitive functional interfaces introduced, which can always takes primitive types as input and return primitive types.Hence autoboxing and autounboxing won't be required,which improves performance.

1. Primitive Type Functional Interfaces for Predicate
     The following are various primitive Functional interfaces for Predicate.
1.IntPredicate: always accepts input value of int type
2.LongPredicate: always accepts input value of long type
3.DoublePredicate: always accepts input value of double type
interface IntPredicate {
   public boolean test(int i);
   //default methods: and(),or(),negate()
}
interface LongPredicate {
   public boolean test(long l);
   //default methods: and(),or(),negate()
}
interface DoublePredicate {
   public boolean test(double d);
   //default methods: and(),or(),negate()
}
Example
import java.util.function.IntPredicate;;
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      int[] x ={0,5,10,15,20,25};
      IntPredicate;<Integer> p=i->i%2==0;
      for (int x1 : x) {
         if(p.test(x1)) {
            System.out.println(x1);
         }
      }
   }
}
     In the above example, autoboxing and autounboxing won't be performed internally.Hence performance wise improvements are there.

2. Primitive Type Functional Interfaces for Function
     The following are various primitive Type Functional Interfaces for Function
1. IntFunction: It can take int type as input and return any type.
public R apply(int i);
2. LongFunction: It can take long type as input and return any type.
public R apply(long i);
3. DoubleFunction: It can take double type as input and return any type.
public R apply(double d);
4. ToIntFunction: It can take any type as input but always returns int type.
public int applyAsInt(T t)
5. ToLongFunction: It can take any type as input but always returns long type.
public long applyAsLong(T t)
6. ToDoubleFunction: It can take any type as input but always returns double type
public int applyAsDouble(T t) 
7. IntToLongFunction: It can take int type as input and returns long type.
public long applyAsLong(int i) 
8. IntToDoubleFunction: It can take int type as input and returns long type.
public double applyAsDouble(int i)
9. LongToIntFunction: It can take long type as input and returns int type.
public int applyAsInt(long i)
10. LongToDoubleFunction: It can take long type as input and returns double type.
public int applyAsDouble(long i)
11. DoubleToIntFunction: It can take double type as input and returns int type.
public int applyAsInt(double i)
12. DoubleToLongFunction: It can take double type as input and returns long type.
public int applyAsLong(double i)
13. ToIntBiFunction: return type must be int type but inputs can be any type.
public int applyAsInt(T t, U u)
14. ToLongBiFunction: return type must be long type but inputs can be any type.
public long applyAsLong(T t, U u)
15. ToDoubleBiFunction: return type must be double type but inputs can be any type.
public double applyAsDouble(T t, U u)
Example 1
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      Function<Integer, Integer> f = i -> i * i;
      System.out.println(f.apply(5));
   }
}
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      IntFunction<Integer> f = i -> i * i;
      System.out.println(f.apply(5));
   }
}
Example 2
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      Function<String, Integer> f = s -> s.length();
      System.out.println(f.apply("Ashok Kumar"));
   }
}
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      ToIntFunction<String> f = s -> s.length();
      System.out.println(f.apply("Ashok Kumar"));
   }
}
3. Primitive Version for Consumer
     The following 6 primitive versions available for Consumer
1. IntConsumer
public void accept(int value)
2. LongConsumer
public void accept(long value)
3. DoubleConsumer
public void accept(double value)
4. ObjIntConsumer
public void accept(T t,int value)
5. ObjLongConsumer
public void accept(T t,long value)
6. ObjDoubleConsumer
public void accept(T t,double value)
Example
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      IntConsumer c= i -> System.out.println("The Sum is : " +(i + i));
      f.accept(100);
   }
}
The Sum is : 200
4. Primitive Versions for Supplier
      The following 4 primitive versions available for Supplier
1. IntSupplier
public int getAsInt()
2. LongSupplier
public long getAsLong()
3. DoubleSupplier
public double getAsDouble()
4. BooleanSupplier
public boolean getAsBoolean()
Example
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      IntSupplier s = () -> (int)(Math.random()*10);
      String otp="";
      for(int i =0;i<6;i++) {
        otp=otp+s.getAsInt();
      }
      System.out.println("The 6 digit OTP : "+otp);
   }
}
Output
The 6 digit OTP : 689542
UnaryOperator<T>
☀ If input and output are same type then we should go for UnaryOperator
☀ It is child of Function<T, T>.
Example
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      Function<Integer, Integer> f = i -> i * i;
      System.out.println(f.apply(10));
   }
}
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      UnaryOperator<Integer> f = i -> i * i;
      System.out.println(f.apply(10));
   }
}
The primitive versions for UnaryOperator 
1. IntUnaryOperator
public int applyAsInt(int)
2. LongUnaryOperator
public long applyAsLong(long)
3. DoubleUnaryOperator
public double applyAsDouble(double)
Example 1
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      UnaryOperator<Integer> f = i -> i * i;
      System.out.println(f.applyAsInt(10));
   }
}
Example 2
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      UnaryOperator<Integer> f1 = i -> i + 1;
      System.out.println(f.applyAsInt(4));

      UnaryOperator<Integer> f2 = i -> i + i;
      System.out.println(f.applyAsInt(4));

      System.out.println(f1.andThen(f2).applyAsInt(4));
   }
}
Output
5
16
25
BinaryOperator
     It is the child of BiFunction<T,T,T>
BinaryOperator<T> public T apply(T,T)
Example
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      BiFunction<String,String,String> f = (s1,s2) -> s1+s2;
      System.out.println(f.apply("Ashok ","Kumar"));
   }
}
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      BinaryOperator<String> b = (s1,s2) -> s1+s2;
      System.out.println(b.apply("Ashok ","Kumar"));
   }
}
The primitive versions for BinaryOperator
1. IntBinaryOperator
public int applyAsInt(int i,int j)
2. LongBinaryOperator
public long applyAsLong(long l1,long l2)
3. DoubleBinaryOperator
public double applyAsLong(double d1,double d2)
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      BinaryOperator<String> b = (i1 , i2) -> i1 + i2;
      System.out.println(b.apply(20, 25));
   }
}
import java.util.function.*; 
/**
 * 
 * @author ashok.mariyala
 *
 */
class Test { 
   public static void main(String[] args) { 
      IntBinaryOperator<String> b = (i1 , i2) -> i1 + i2;
      System.out.println(b.apply(20, 25));
   }
} 

Next Tutorial : Method and Constructor references using (::) Operator

Previous Tutorial : Bi-Functional Interfaces

No comments:

Post a Comment