Primitive Type Functional Interfaces

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()
}

E.g

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)

E.g 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));
   }
}

E.g 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)

E.g

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()

E.g

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); // 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>.

E.g

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)

E.g

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));
   }
}
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));
   }
}
BinaryOperator

It is the child of BiFunction<T,T,T>

BinaryOperator<T> public T apply(T,T)
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)

E.g

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));
   }
} 

Primitive Type Functional Interfaces


Scroll to top