Java/Basic

[Java-Basic] 함수형 인터페이스 (Functional Interface) 예제

Jeong Jeon
반응형

Java 개발자인데 모르는것들이 너무 많아 하나하나 공부하다보니, 함수형 인터페이스를 접하게되었다.

우선 사용법에 대해 알아보자..!

 

함수형 인터페이스를 사용하는 이유?

자바의 람다식은 함수형 인터페이스로만 접근이 가능하기 때문에, 람다식 사용시 미리 정의된 인터페이스를 사용할 수 있다.

  • java.lang.function 패키지

Function<T, R>

T 타입의 input을 받아, R 타입을 Return하는 함수 인터페이스

주로 매개변수를 반환값 타입으로 변환 후 반환할때 사용한다.

 

사용 : 타입 변환 예제가 아닌 단순한 덧셈 곱셈 예제로 만들었다...

apply() 메소드를 오버라이드 하여 input + 10하는 메소드로 만들어보자.

import java.util.function.Function;

public class MyFunction implements Function<Integer, Integer>{

	@Override
	public Integer apply(Integer t) {
		return t+ 10;
	}

	public Integer apply(String t) {
		return Integer.parseInt(t)+ 10;
	}
}

 

다양한 방법으로 사용해보자

import java.util.function.Function;

public class testMain {

	public static void main(String[] args) {

		//1).Fucntion Class를 만들어 apply()메소드 Override 하는 방법
		int a = 10;
		MyFunction myfunc = new MyFunction();
		System.out.println("result-override : "+ myfunc.apply(a));

		//2-1).Function을 만들어서 사용하는 두가지 방법
		Function<Integer,Integer> multiFirst = (i) -> {
			return i * 2;
		};
		int result1 = multiFirst.apply(10);
		System.out.println("result1 : "+result1);
		//2-2).
		Function<Integer,Integer> multiSecond = (i)-> i * 2;
		int result2 = multiSecond.apply(10);
		System.out.println("result2 : "+result2);

		//3). 입력값을 String으로 넣었을때 -> 별도 메소드 제작 => 당연히 가능
		int result = myfunc.apply("10");
		System.out.println("result3 : "+result);
	}
}

 

결과 : 

result-override : 20
result1 : 20
result2 : 20
result3 : 20

 

Function은 andThen 메소드와 compose 메소드를 합쳐서 사용도 가능하다.

andThen() : 앞의함수 (myfunc.apply)를 먼저 적용한뒤, 뒤에있는 함수(multiFirst)를 적용시킨다.

compose() : 뒤에오는 함수를 적용(multiFirst) 한 후 이 값을 가지고 myfunc의 입력값으로 사용한다.

Function<Integer,Integer> composeFunction = myfunc.compose(multiFirst);
int result4 = composeFunction.apply(100);
System.out.println("result4 : "+result4);

결과 :

result4 : 210

 

Runnable

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

대체로 Thread를 사용할때 많이 봤을거라고 생각합니다.

public interface Runnable{
  public abstract void run();
}

사용 : 
Runnable runnable = () -> System.out.println("작동");
runnable.run();

결과 : 

작동

 

Supplier<T>

인자를 받지 않고 T타입의 리턴을 하는 인터페이스

public interface Supplier<T> {
    T get();
}

사용 : 
Supplier<String> s = () -> "작동";
String abc = s.get();
System.out.println(abc);

결과 : 

작동

 

Consumer<T>

T타입의 객체를 인자로 받고 리턴값은 없는 인터페이스 => 객체를 사용하여 정의한 로직을 수행하는 아이.

accept 메소드를 사용한다.

방식-1
MyConsumer myconsumer = new MyConsumer() {
		@Override
			public void accept(String input) {
				System.out.println("작동"+input);
			}
		};
myconsumer.accept("합니다.");

방식-2
MyConsumer m = s->System.out.println(s+"합니다.");
m.accept("작동");

결과 :

작동합니다.
작동합니다.

 

Predicate<T>

T타입 Input을 받고 boolean을 return하는 인터페이스

미리 정의한 함수를 적용하여 boolean값을 리턴하는 아이이다..!

Predicate<Integer> isBiggerThanSeven = num -> num > 7;
System.out.println("10 is bigger than 7? -> " + isBiggerThanSeven.test(10));
Predicate<Integer> isSmallerThanSeven = num -> num < 7;
System.out.println("10 is Smaller than 7? -> " + isSmallerThanSeven.test(10));

 

결과 : 

10 is bigger than 7? -> true
10 is Smaller than 7? -> false

 

나머지 BiConsumer, intConsumer 등이 있지만 우선 기본적인것 부터 차근차근 알아보았다.

 

정리

Function<T, R>

R apply(T t);

- T를 인자로 받고, R을 리턴

Consumer<T>

void accept(T t);

- T를 인자로 받고, 이를 소모(리턴 X)

Predicate<T>

boolean test(T t);

- T를 인자로 받고, Boolean형을 리턴

Supplier<T>

T get();

- T를 리턴합니다.(Lazy Evaluation)

 

오늘도 화이팅!

반응형