JAVA Programming

Growing_HJ·2024년 6월 5일

일기장

목록 보기
20/51

2024.06.05.WED <D + 16> 함수형 인터페이스
A. 함수형 인터페이스

  • 함수를 어떤 메소드의 매개변수로 사용하고 싶은 경우, 매개변수에는 타입이 존재하고, 함수를 나타내는 타입의 필요성이 나온다.
    ex) 타입 f = (a,b) -> a > b ? a : b ; //함수 형태
  • 람다식을 메소드라고 생각하고, 람다식을 호출해서 사용하려고 한다면, 기존에는 객체를 생성하여 메소드에 접근해서 사용한다.
  • 위의 람다식이 어떤 타입의 변수에 저장되려면, 람다식은 눈에 보이지는 않지만,
    지금 람다식이 익명클래스 안에 있는 것은 아닌지 생각해 보아야 한다.
    A-1. 함수형 인터페이스의 제약조건
  1. 함수형 인터페이스에는 오직 하나의 추상 메소드만 정의되어있어야 함.
    -> 람다식과 인터페이스가 1:1 매핑 가능 (!but! static 메소드, default 메소드의 개수에는 제약이 없음)
new Object() { //익명 클래스
	int (int a, int b) {
    	return a > b ? a : b ;
    }
}
타입 f = (a,b) -> a > b ? a : b;
MyFunc f = (a,b) -> a > b ? a : b;

@FunctionalInterface 
@FunctionalInterface 사용시 함수형 인터페이스가 올바르게 정의가 되었는지를 확인 가능. 
interface MyFunc {
	public abstract int max(int a, int b);
}
MyFunc f = new MyFunc() { // 인터페이스를 구현한 익명클래스
// MyFunc 인터페이스의 추상메소드인 max를 구현
 public int max(int a, int b) {
 		return (a,b) -> a > b ? a : b;
 	}
};
사용시 int big = f.max(3,5); //익명 객체의 메소드 호출

결론) 람다식을 어떤 메소드의 매개변수로 전달이 가능해지고,
MyFunc 인터페이스는 람다식을 다루기 위한 인터페이스가 되고, 이를 "함수형 인터페이스" 라고 함.

// 함수형 인터페이스 생성하기  
@FunctionalInterface
interface MyFunc {
	public abstract void run(); //추상메소드임
	
}

public class LambdaEx1 {
	// 메인에서 사용해야 하니 static 으로 작성
	// 함수형 인터페이스를 매개변수로 활용하는 메소드 생성하기
	static void execute(MyFunc f) {
		f.run();
	}
	
	// 함수형 인터페이를 반환형으로 하는 메소드 생성하기 
	static MyFunc getMyFunc() {
		MyFunc f = () -> System.out.println("f3.run()"); //f를 의미 
		return f;
	}
	
	public static void main(String[] args) {
		// case1. 함수형 인터페이스로 람다식 선언하기.
		MyFunc f1 = () -> System.out.println("f1. run()");
		
		// case2. 익명클래스 형태의 함수형 인터페이스 구현하기. 
		MyFunc f2 = new MyFunc() {
			// 함수형 인터페이스의 추상메소드를 구현. 
			@Override
			public void run() {
				System.out.println("f2. run()");
			}
		};
		
		// case3. getMyFunc() 사용하기
		MyFunc f3 = getMyFunc();
		
		// case4. 매개변수 execute() 사용하기.
		// case4.1. 함수형 인터페이스를 매개변수로 전달하는 방법
		execute(f1);
		
		// case4.2. 함수형 인터페이스 없이 직접 람다식으로 전달하는 방법
		execute(() -> System.out.println("run"));
		
		f1.run();
		f2.run();
		f3.run();		
	}
}

B. 함수형 인터페이스의 JAVA API
JAVA API의 사용 목적
1. Stream의 API문서를 보고 사용하기 위함.
-> Stream의 메소드를 사용해야 하는데, 이때 각 메소드의 매개변수를 이해하고 사용하기 위함.

B-1. 매개변수가 없거나 하나인 함수형 인터페이스 (종류 및 의미를 이해!)
a. Supplier - 매개변수는 없고 반환값만 있음.
b. Consumer - 매개변수만 있고 반환값이 없음.
c. Function<T, R> - 일반적인 함수. 하나의 매개변수를 받아 처리 후, 결과를 반환.
d. Predicate - 조건식을 표현할 때 사용함. 매개변수는 하나, 반환타입이 boolean.

B-2. 매개변수가 두개인 함수형 인터페이스 (종류 및 의미를 이해!)
a. BiConsumer<T, U> - 2개의 매개변수가 있고 반환값이 없음.
b. BiFunction<T, U, R> - 일반적인 함수. 두개의 매개변수를 받아 처리 후, 결과를 반환.
c. BiPredicate<T, U> - 조건식을 표현할 때 사용함. 매개변수는 두개, 반환타입이 boolean.

B-3. Operator
a. UnaryOperator (Unary: 단항)
UnaryOPerator
-> 매개변수가 하나이고, 매개변수와 결과값의 타입이 동일한 경우.
Function와 동일, 차이점은 매개변수와 결과의 타입이 동일한 것.
b. BinaryOperator (Binary: 이항)
-> 매개변수가 두개이고, 매개변수와 결과의 타입이 동일한 경우.
BiFunction와 동일, 차이점은 매개변수와 결과의 타입이 동일한 것.
B-4. 함수형 API가 매개변수로 사용되는 JAVA API메소드.

  • Map : Key, Value로 구성된 자료형. 따라서 데이터 추가시 매개변수가 2개임.

B-5. 반복문 돌리기

  • void forEach (BiConsumer<T , U> action)
    -> Map의 모든 요소에 작업 action을 수행.
public class LambdaEx2 {
	public static void main(String[] args) {
		// 데이터 소스 (ArrayList) => Collection(List, Set, Map (Collection의 인터페이스 종류))
		ArrayList<Integer> list = new ArrayList<>();
		
		for (int i = 0; i < 10; i++) 
		{  list.add(i);  }
		
		// forEach
		// forEach의 함수형 인터페이스 : Consumer<? super E> action
		// 매개변수가 있고 반환값이 없음.
		list.forEach(i -> System.out.println(i + ", "));
		System.out.println();
		
		// removeIf()
		// 함수형 인터페이스 : Predicate<? super E> filter 
		list.removeIf(i -> i % 2 == 0);
		System.out.println(list);
		
		// replaceAll
		// 함수형 인터페이스 : UnaryOperator<E> operator
		// Function<T> 와 차이점 : 매개변수 타입과 반환 타입이 동일한 점. 
		list.replaceAll(i -> i * 10);
		
		// Map 생성하기 (데이터 소스)
		Map<String, String> map = new HashMap<String, String>();
		map.put("1", "1");
		map.put("2", "2");
		map.put("3", "3");
		map.put("4", "4");
		
		// forEach()
		// 함수형 인터페이스 : BiConsumer<? super K, ? super V> action
		// 매개변수가 두 개 이고, 반환값이 없는 경우.
		// (K, V) -> System.out.println("{" + k + ", " + v + "}")
		map.forEach((k,v) ->System.out.println( "{" + k + ", " + v + "}"));
		System.out.println();
	}

}  

0개의 댓글