(매개변수) -> 함수바디(구현부)

interface 변수 = 람다식(함수구현);           ex ) MyFunction f1 = () -> System.out.println("출력");

 

- 객체지향언어인 자바를 함수형 언어로 사용

- 익명 함수 (반환타입 X, 메서드 이름 X)

- 익명 클래스의 객체임 (람다식으로 만들때 익명 클래스, 인터페이스 모두 생략)

- 람다식(함수)에서 로컬변수(람다식을 쓰고있는 메서드에 정의된 변수)를 쓰고 싶으면 final로 설정해야 함 (but, default값이 final)   -> 메서드 안의 메서드에서 사용하려면 outer 메서드에서 그 변수를 final로 설정해야 함.

  하지만, 계산하고 싶으면 바깥메서드의 로컬변수가 아닌 class 영역에 멤버변수로 설정(∵멤버변수는 사용 가능)

 

▷익명클래스 -> 람다식

LambdaInterface f1 = new LambdaInterface() {
   
    @Override
    public void method() {
	  System.out.println("출력");
	}
}; 
		    ↓
		
		
LambdaInterface f1 = () -> {
	System.out.println("출력");
};

▷ 로컬변수

class Outer {
	int iv = 10;		// iv
	void method() {
		int iv = 40;		// lv (기본값 : final)
		LambdaInterface f = () -> {
//		    int iv = 50; // 같은 local안에 iv 중복 X
//		    iv = 50; 	// final이라 수정 X
		    System.out.println(Outer.this.iv);		//10
		    System.out.println(this.iv);		//10
		    System.out.println(iv);			//40
		};
		f.method();
	}
       
}

메서드[method()] 내의 내부클래스(인터페이스)[LambdaInterface]의 메서드가 람다식으로 구현

안의 메서드[람다식-익명함수]에서 바깥메서드[method()]의 변수[iv = 40]를 사용하려면 final로 설정해야함.

 

 

 

○ 람다식 생략 방법

- 매개변수의 타입도 생략가능

- { }안에 문장이 한 줄일 때 { }생략가능 (단, return문 일때는 { return     }; 생략)

  -> 문장이 아닌 식일경우 { return     ;} 생략 가능

- 매개변수가 하나일 때 ( ) 생략가능

 

 

● 함수형 인터페이스(@functionalInterface)

 - 람다식을 다루기 위한 인터페이스, 단 하나의 추상메서드만 선언되어 있음

 - 구현시 그 하나의 메서드를 구현하는 것임 (람다식과 인터페이스의 메서드가 1:1 연결)

 - 일반 인터페이스처럼 디폴트 메서드와 static 메서드도 갖을 수 있음(추상메서드만 하나면 됨)

@FunctionalInterface
interface MyFunction {
    void print();
}

public class lambdaEx {
	public static void main(String[] args) {
       		MyFunction f1 = () -> System.out.println("출력");	// 구현
        	f1.print();		// 실행
	}

}

○ function 패키지 : 함수형 인터페이스를 미리 구현

  → 매개변수나 반환값이 1개이하 함수형 인터페이스

함수형 인터페이스 메서드 매개변수 리턴값
java.lang.Runnable void run() . .
Supplier<T> T get() . <T>
Cousumer<T> void accept(T t) <T> .
Function<T, R> R apply(T t) <T> <R>
Predicate<T> boolean test(T t) <T> (Boolean)
UnaryOperator<T> T apply(T t) <T> <T>

Function 인터페이스 : 주로 매개값(T)을 리턴값(R)으로 매핑(타입변환)할 경우 사용

Predicate 인터페이스 : Function의 변형, Boolean값을 반환

Operator 인터페이스 : Function의 변형, 매개변수타입과 리턴값의 타입이 같음.

 

 → 매개변수가 2개인 함수형 인터페이스

함수형 인터페이스 메서드 매개변수 리턴값
BiCousumer<T, U> void accept(T t, U u) <T, U> .
BiFunction<T, U, R> R apply(T t, U u) <T, U> <R>
BiPredicate<T, U> boolean test(T t, U u) <T, U> (Boolean)
BinaryOperator<T, T> T apply(T t, T t) <T, T> <T>
Consumer<String> c = (t) -> System.out.println(t+8);		

                       ↓

Consumer<T> c = new Consumer() { 
    void accept(T t) {
        System.out.println(t+8); 
    }
};
=======================================1===============================
printString(t -> t.getName());

               ↓
               
Function<Student, String> f = t -> t.getName();
printString(f);
    
               ↓

Function<Student, String> f = new Function<Student, String>() {

    @Override
    public String apply(Student t) {
        return t.getName();
    }
};
printString(f);

  
=======================================2===============================  
printString(t -> t.getName());

                ↓

printString(new Function<Student, String>() {

    @Override
    public String apply(Student t) {
        return t.getName();
    }
});




private static void printString(Function<Student, String> f) {
    System.out.println(f.apply(t));
}

 

● andThen(),  compose()

 - Function 인터페이스의 default 메서드

 - 두개의 함수식 인터페이스를 순차적으로 연결해 실행, 첫번째 리턴 값을 두번째 매개값으로 이용하여 최종값 도출.

 - andThen() : 앞→뒤                 ex) f1<T, R>.andthen(f2<R, V>)   == T,R -> R,V [최종 V리턴타입] (f1 -> f2)

 - compose() : 앞←뒤                ex) f1<T, R>.compose(f2<V, T>)   == V,T -> T,R [최종 R리턴타입] (f2 -> f1)

 

and(), or(), negate()

 - Predicate 인터페이스의 default 메서드

 - and() : && 대응 -> 두 Predicate가 모두 true면 최종 true 리턴        ex) p12 = p1.and(p2);

 - or() : || 대응 -> 두 Predicate 중 하나만 true면 최종 true 리턴          ex) p12 = p1.or(p2);

 - negate() : ! 대응-> Predicate 결과가 true이면 false, false이면 true    ex) p12 = p1.negate();

 

● 메서드 참조

 - 람다식에서 불필요한 매개변수를 제거하는 목적 (함수형 인터페이스의 타입을 보고 매개변수의 타입을 충분히 알아 낼 수 있음)

 - 함수형 인터페이스와 사용할 메소드의 매개변수 갯수와 타입이 같아야만 사용 가능. 제너릭 참조인 경우에만 사용 가능 

○ static, 인스턴스 메서드 참조

// static 메서드
IntBinaryOperator operator;
operator = (x, y) -> Calculator.staticMethod(x, y);
System.out.println(operator.applyAsInt(1, 2));
operator = Calculator::staticMethod;
System.out.println(operator.applyAsInt(1, 2));

// 인스턴스 메서드
Calculator obj = new Calculator();
operator = (x, y) -> obj.instanceMethod(x, y);
System.out.println(operator.applyAsInt(1, 2));
operator = obj::instanceMethod;
System.out.println(operator.applyAsInt(1, 2));

○ 매개변수의 메서드 참조 (a의 타입 :: 메서드)

ToIntBiFunction<T, U> function;
function = T :: int compareToIgnoreCase(U);

ex)
ToIntBiFunction<String, String> function;
function = (a,b) -> a.compareToIgnoreCase(b);
			   ↓
function = String :: compareToIgnoreCase;

○ 생성자와 배열

// 생성자
Function<Integer, Myclass> f = (i) -> new MyClass(i);	
                       ↓
Function<Integer, Myclass> f = MyClass::new;	


// 배열
Function<Integer, int[]> f = x -> new int[x];
                       ↓
Function<Integer, int[]> f = int[]::new;

'Langauge > JAVA' 카테고리의 다른 글

입출력(I/O)  (0) 2020.06.10
스트림(Stream)  (0) 2020.06.04
어노테이션(Annotation)  (0) 2020.06.01
열거형(Enum)  (0) 2020.06.01
쓰레드(Thread)  (0) 2020.05.31

+ Recent posts