[자바기초] 함수형 이터페이스

함수형 인터페이스는 1개의 추상 메소드를 갖고 있는 인터페이스이다.

  public interface FunctionalInterface{
    public abstract void doSomething(String text);
  }

사용하는 이유?

함수형 인터페이스를 사용하는 이유는 자바의 람다식이 함수형 인터페이스로만 접근이 되기 때문입니다.

지금까지는 익명 클래스로 객체를 만들어 왔는데 람다식을 이용하면 간단하게 표현할 수 있다.

  public interface FunctionalInterface{
    public abstract void doSomething(String text);
  }
  
  // 익명클래스 대신 람다식 사용
  FunctionInterface func = text -> System.out.println(text);
  func.doSomething("do something")';
  
  // 실행 결과는 do something

기본 함수형 인터페이스

java.util.function 패키지에 많은 것들이 정의 되어있다.

Runnable

Runnable 은 인자를 받지도 않고 리턴값도 없는 인터페이스이다.

  public interface Runnable{
    public abstract void run();
  }
  
  Runnable runnable = () -> System.out.println("run anything!");
  runnable.run();

Supplier

Supplier는 인자를 받지 않고 T타입의 객체를 리턴합니다.

  public interface Supplier<T>{
    T get();
  }
  
  Supplier<String> getString = ()- > "Happy new year!";
  String str = getString.get();
  System.out.println(str);  //  Happy new year! 가 출력

Consumer

Consumer는 T타입의 객체를 인자로 받고 리턴 값은 없습니다,

  public interface Consumer<T>{
    void accept(T t);
    
      default Consumer<T> andThen(Consumer<? super T> after){
        Objects.requireNonNull(after);
        return (T t)-> {accept(t); after.accept(t);};
      }
  }
  
  Consumer<String> printString = text -> System.out.println("Miss "+text+"?");
  printString.accept("me");
  
  Consumer<String> printString = text -> System.out.println("Miss "+ text + "?");
  Consumer<String> printString2 = text -> System.out.println("--> Yes");
  printString.andThen(printString2).accept("me");
  
  /*
    결과는 다음과 같다.
    
    Miss me?
    --> Yes
  */

Function

Function<T,R> 은 T타입의 인자를 받고, R타입의 객체를 리턴합니다.

  public interface Function<T,R>{
    R apply(T t);
  }
  
  Function<Integer, Integer> multiply = (value) -> value * 2;
  Integer result = multiply.apply(3);
  System.out.println(result);

Predicate

Predicate는 T타입 인자를 받고 결과로 boolean을 리턴합니다.

  public interface Predicate<T>{
    boolean test(T t);
  }
  
  Predicate<Integer> isBiggerThanFive = num -> num > 5;
  System.out.println("10 is bigger than 5? -> "+ isBiggerThanFive.test(10));

UnaryOperator

하나의 인자와 리턴 타입을 가진다. 여기까진 Funcion 같지만 파라미터는 1개다.

이유는 인자의 타입과 리턴타입이 서로 같아야하기 때문이다!

  UnaryOperator<String> u = str -> str + " operator";
  String result = u.apply("hello unary");

BinaryOperator

동일한 타입의 인자 2개와 같은 타입의 리턴타입을 가진다.

  BinaryOperator<String> b = (str1,str2) -> str1 +" " + str2;
  String result = b.apply("hello", "binary");

BiPredicate<T,U>

서로 다른 2개의 인자를 받아 boolean 타입으로 반환

  BiPrediacate<String, Integer> bp = (str,num) -> str.equals(Integer.toString(num));
  boolean result = bp.test("1",1);

BiConsumer<T,U>

서로 다른 2개의 인자를 받아 소모한다.

  BiConsumer<String, Integer> bc = (str,num) -> System.out.println(str+"::"+num);
  bc.accept("숫자",5);  // 숫자::5 출력

BiFunction<T,U,R>

서로 다른 타입의 2개의 인자를 받아 또 다른 타입으로 반환한다.

  BiFunction<Integer,String,String> bf = (num, str) -> String.valueOf(num) + str;
  String result = bf.apply(5,"678");  // 5678 출력