Java - Functional Interface

1. Functional interface

1.1 Concept

Functional interface:

  • an interface with one and only one abstract method;
  • The embodiment of functional programming in Java is Lambda expression;

To check if an interface is a functional interface:

  • Add @FunctionlIterface annotation, if the interface is not a functional interface, an error will be reported;

Note:

  • The @FunctionlIterface annotation is optional. Even if you don’t write this annotation, you can use Lambda expressions as long as the interface is a functional interface. In order to avoid mistakes in writing, it is recommended to add this annotation;

Example:

@FunctionalInterface
public interface MyIterface {
  void show();
}

public class MyIterfaceDemo {
  public static void main(String[] args) {
      MyIterface myIterface = ()-> System.out.println("functional interface");
      myIterface.show();
  }
}

1.2 Use of functional interfaces

When a functional interface is used as a parameter of a method:

  • If the parameter of the method is a functional interface, we can use Lambda expressions to pass as parameters;
public class RunnableDemo {
  public static void main(String[] args) {
      //Called by anonymous inner class
      startThread(new Runnable() {
          @Override
          public void run() {
              System.out.println(Thread.currentThread().getName() + ":Anonymous inner class starts thread");
          }
      });
		//Invoke by way of Lambda expression
      startThread(()-> System.out.println(Thread.currentThread().getName() + ":Lambda The expression starts the thread"));
  }

  private static void startThread(Runnable r){
      new Thread(r).start();
  }
}

When the functional interface is used as the return value of the method:

  • If the return value of the method is a functional interface, you can use a Lambda expression as the return result;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class ComparatorDemo {
  public static void main(String[] args) {
      List<String> list = new ArrayList<>();

      list.add("cccc");
      list.add("bb");
      list.add("ddd");
      list.add("a");
      System.out.println("Before sorting:" + list);

      Collections.sort(list,getComparator());

      System.out.println("After sorting:" + list);
  }
  private static Comparator<String> getComparator(){
  	//anonymous inner class
//        return new Comparator<String>(){
//            @Override
//            public int compare(String o1, String o2) {
//                return o1.length() - o2.length();
//            }
//        };
		//Lambda expressions
      return (s1,s2)->s1.length()-s2.length();
  }
}

1.3 Supplier interface

Supplier contains a no-argument method:

  • T get(): get the result;
  • This method does not require parameters, it will return a data according to the implemented logic;
  • The Supplier interface is also called a production interface;

Example:

import java.util.function.Supplier;

public class SupplierDemo {
  public static void main(String[] args) {
      System.out.println(getString(()->"Ultraman"));
      System.out.println(getString(()->45));
      System.out.println(getString(()->!true));
  }

  private static Object getString(Supplier<Object> sup){
      return sup.get();
  }
}

Note,

  • The type specified in the example is Object, so all types of data can be received, and if the type is specified, only the data of the specified type can be received;
  • The type replaced by the generic T in Supplier can only be an encapsulation class, such as String , Integer, etc.;

1.4 Consumer interface:

Consumer contains two methods:

  • void accept(T t): perform an operation on the given parameter;

Example 1:

import java.util.function.Consumer;

public class CondumerDemo1 {
   public static void main(String[] args) {
       //Lambda expressions
       operatorString("Zhang San",s-> System.out.println(s));
       //method reference
       operatorString("Li Si", System.out::println);
   }

   private static void operatorString(String name, Consumer<String> con){
       con.accept(name);
   }
}
  • default Consumer andThen(Consumer after): returns a sequence by which the Consumer performs this operation, followed by the after operation;

Example 2:

import java.util.function.Consumer;

public class CondumerDemo2 {
   public static void main(String[] args) {
       String[] strArray = {"Zhang San,18","Li Si,20","Wang Wu,19"};

       printInfo(
               strArray,
               str-> System.out.print("Name:" + str.split(",")[0]),
               str-> System.out.println(",age:" + Integer.parseInt(str.split(",")[1]))
       );
   }

   private static void printInfo(String[] strArray, Consumer<String> con1, Consumer<String> con2){
       for (String str : strArray) {
           con1.andThen(con2).accept(str);
       }
   }
}

1.5 Predicate interface

Predicate has five methods:

  • boolean test(T t): judge the given rules;

Example 1:

import java.util.function.Predicate;

public class PredicateDemo1 {
   public static void main(String[] args) {
       //the result is false
       System.out.println(useJudge("Zhang San likes to eat watermelon",s->s.length() > 8));
   }
   private static boolean useJudge(String s, Predicate<String> pre){
       return pre.test(s);
   }
}
  • default Predicate and(Predicate other): return the judgment of short-circuit logic and;

Example 2:

import java.util.function.Predicate;

public class PredicateDemo2 {
   public static void main(String[] args) {
       //the result is false
       System.out.println(useJudge("Zhang San likes to eat watermelon", s->s.length() > 2, s -> s.length() < 7));
   }
   private static boolean useJudge(String s, Predicate<String> pre1, Predicate<String> pre2){
       return pre1.and(pre2).test(s);
   }
}
  • default Predicate or(Predicate other): returns the judgment of short-circuit logic or;

Example 3:

import java.util.function.Predicate;

public class PredicateDemo3 {
   public static void main(String[] args) {
       //the result is true
       System.out.println(useJudge("Zhang San likes to eat watermelon", s->s.length() > 2, s -> s.length() < 7));
   }
   private static boolean useJudge(String s, Predicate<String> pre1, Predicate<String> pre2){
       return pre1.or(pre2).test(s);
   }
}
  • default Predicate negate(): Returns a predicate representing the logical negation of the predicate, which is equivalent to a logical NOT operation;

Example 4:

import java.util.function.Predicate;

public class PredicateDemo4 {
   public static void main(String[] args) {
       //the result is true
       System.out.println(useJudge("Zhang San likes to eat watermelon",s->s.length() > 8));
   }
   //Determine whether the given string meets the requirements
   private static boolean useJudge(String s, Predicate<String> pre){
       return pre.negate().test(s);
   }
}
  • static Predicate isEqual(Object targetRef): first judge whether the parameter is null, and if it is not null, perform the equals() operation;

Example 5:

import java.util.function.Predicate;

public class PredicateDemo5 {
   public static void main(String[] args) {
       //the result is false
       System.out.println(useJudge("Zhang San likes to eat watermelon","Zhang San doesn't like eating watermelon"));
   }
   private static boolean useJudge(String s1, String s2){
       return Predicate.isEqual(s1).test(s2);
   }
}

1.6 Function interface

Function<T,R>: There are two commonly used methods

  • R apply(T t): applies this function to the given arguments;

Example 1:

import java.util.function.Function;

public class FunctionDemo {
   public static void main(String[] args) {
       //Lambda expressions
       convert("123",s->Integer.parseInt(s));
       //method reference
       convert("123",Integer::parseInt);
   }

   private static void convert(String s, Function<String,Integer> fun){
       System.out.println(fun.apply(s));
   }
}
  • defaultFunction andThen( Function after ): returns an input that is first taken by the function, and then the result of the after function;

Example 2:

import java.util.function.Function;

public class FunctionDemo {
   public static void main(String[] args) {
       toConvert(
               "100",
               s -> Integer.parseInt(s),
               s -> String.valueOf(s + 25)
               );
   }
   private static void toConvert(String s, Function<String,Integer> fun1,Function<Integer,String> fun2){ 
       System.out.println(fun1.andThen(fun2).apply(s));
   }
}

Tags: Java

Posted by echion on Thu, 17 Nov 2022 12:31:21 +0530