JAVA4_01_람다식

charl hi·2021년 10월 3일
0

JAVA4

목록 보기
1/13

링크텍스트

람다식 Lambda Expression

정의

  • 함수(메소드)를 간단한 식(expression)으로 표현하는 방법
  • 익명 함수, 이름이 없는 함수, anonymous function

함수와 메소드의 차이

  • 근본적으로 동일
  • 함수는 일반적 용어, 메소드는 객체지향개념 용어
  • 함수는 클래스에 독립적, 메소드는 클래스에 종속적

✨작성 방법

  1. 메소드명과 반환타입 제거하고, ->를 구현부블록{} 앞에 추가한다.
int max(int a, int b) {
	return a > b ? a : b;
}

->

(int a, int b) -> {
	return a > b ? a : b;
}
  1. 반환값이 있는 경우 : 식이나 값만 적고 return문 생략 가능(끝에 ; 안 붙임)

->

(int a, int b) -> a > b ? a : b
  1. 매개변수의 타입이 추론가능하면 생략 가능(대부분 생략가능)

->

(a, b) -> a > b ? a : b

주의사항

  1. 매개변수가 하나인 경우 : 괄호() 생략 가능(타입이 없을 때만)
a -> a * a		//(O)
(int a) -> a * a	//(O)

(a) -> a * a		//(O)
int a -> a * a		//(X)
  1. 구현부블록{} 안의 문장이 하나일 때 : 괄호{} 생략 가능(; 안 붙임)
(int i) -> System.out.println(i)
  1. return문 생략하지 않을 때 : 괄호{} 생략 불가
(int a, int b) -> { return a > b ? a : b }	//(O)
(int a, int b) -> a > b ? a : b			//(O)

(int a, int b) -> return a > b ? a : b		//(X)



	//메소드 -> 람다식으로 바꿔보자
	//1.
	int max(int a, int b) {
		return a > b ? a : b;
	}
	//->
	(a, b) -> a>b ? a:b
			
	//2
	void printVar(String name, int i) {
		System.out.println(name+ "="+i);
	}
	//->
	(name, i) -> System.out.println(name+"="+i)
	
	//3
	int square(int x) {
		return x*x;
	}
	//->
	x -> x*x
	
	
	//4
	int roll() {
		return (int)(Math.random()*6);
	}
	//->***매개변수가 없을 땐 괄호()생략 안됨!!
	() -> (int)(Math.random()*6)


람다식은 익명 객체!!

  • ✨✨람다식은 익명 함수가 아니라 익명 객체이다!!

  • 위에 예시로 쓴 람다식은 아래와 같다.

new Object() {
	int max(int a, int b) {
		return a > b ? a : b;
	}
}
  • 따라서 ✨✨참조변수로 다뤄야 한다!!

  • 익명클래스 선언, 객체 생성 동시에 하는 방법

new 조상클래스/인페명 { ... };

그러나

	Object obj = new Object() {
		int max(int a, int b) {
			return a>b ? a:b;
		}
	};
	
	int value = obj.max(3, 5);
  • 📢📢문제 발생!!
    -> 1. 타입캐스팅을 해야하는데, 어떻게 해야하는가?
    -> 2. The target type of this expression must be a functional interface.

이를 해결해주는 게 함수형 인터페이스!!

즉, ✨✨✨함수형 인터페이스 타입의 참조변수로 람다식을 다뤄야 한다!!



함수형 인터페이스

  • 단 하나의 추상 메소드만 선언된 인터페이스

1.

@FunctionalInterface
interface MyFunction {
	public abstract int max(int a, int b);
}

2.

+ 익명클래스로 직접 구현

MyFunction f = new MyFunction() {
	public int max(int a, int b) {
		return a > b ? a : b;
	}
};
//**(O) MyFunction에 max()가 있으니까!
int value = f.max(3, 5);

+ 람다식

MyFunction f = (a, b) -> a > b? a : b;
int value = f.max(3, 5);
//실제로는 람다식(익명함수)이 호출됨


ex14_00


class Ex14_00 {
	
	public static void main(String[] args) {
		//익명클래스로 직접 구현
		MyFunction2 f = new MyFunction2() {
			@Override
			public int max(int a, int b) {	//***public!!
				return a>b? a:b;
			}
		};//MF
		int value = f.max(3, 5);
		System.out.println("value= "+value);
		
		//람다식***
		MyFunction2 f2 = (a, b) -> a>b? a:b;
		int value2 = f2.max(3, 5);
		System.out.println("value2= "+value2);
	}//main

}

@FunctionalInterface
interface MyFunction2{
	public abstract int max(int a, int b);
}

value= 5
value2= 5


함수형 인페 & 람다식을 활용한 Comparator

  • Comparator도 FunctionalInterface로, 하면 된다?

점점 작성하는 것이 너무 귀찮아져서 그만....ㅎㅎ

Comparator, Comparable, sort()



ex14_001

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Ex14_001 {

	public static void main(String[] args) {
		List<String> list = Arrays.asList("abc", "aaa", "bbb", "ddd", "aaa");
		Collections.sort(list, (s1, s2) -> s2.compareTo(s1));
//		Collections.sort(list, new Comparator<T>() {
//			public int compare(String s1, String s2) {
//				if(s1 instanceof Comparable && s2 instanceof Comparable) {
//					Comparable c1 = (Comparable) s1;
//					Comparable c2 = (Comparable) s2;
//					return s2.compareTo(s1);	//역순
//				}
//				return -1;
//			}
//		});
		//이 방식은 자꾸 에러나서 못하겠다 ㅠㅠㅠ
		System.out.println("list = "+list);

	}

}
//기본적으로 이렇게 되어있어, 아래가 없어도 작동한다!
@FunctionalInterface
interface Comparator<T>{
	public abstract int compare(T o1, T o2);
}

list = [ddd, bbb, abc, aaa, aaa]


ex11_07 추가

import java.util.Arrays;
import java.util.Comparator;

public class Ex11_07 {

	public static void main(String[] args) {
		String[] strArr = {"cat", "Dog", "lion", "tiger"};
		
		Arrays.sort(strArr, (s1, s2) -> s2.compareTo(s1));
		System.out.println("strArr = "+Arrays.toString(strArr));

		Arrays.sort(strArr, new Descending());
		//이번엔 직접 만든 기준을 담은 객체를 호출한다.+역순
		System.out.println("strArr = "+Arrays.toString(strArr));
		
	}

}
//마찬가지!! 아래가 없어도 잘 작동함
@FunctionalInterface
interface Comparator1{
	public abstract int compare(Object o1, Object o2);
}

//둘다 되는데 뭐가 맞는지 모르겠다.
@FunctionalInterface
interface Comparator1<T>{
	public abstract int compare(T o1, T o2);

//기존의 compare()를 역순을 배출하는 메소드로 오버라이딩하기
//따라서 compare()를 갖고 있는 Comparator를 구현해야 한다.
class Descending implements Comparator{
	public int compare(Object o1, Object o2) {
		//Comparable이 o1, o2의 조상타입클래스 또는 구현된인터페이스라면
		//이 문제에선, String implements Comparable 이므로 true
		//왜 Comparable?? : compareTo()를 쓰려고
		if(o1 instanceof Comparable && o2 instanceof Comparable) {
			Comparable c1 = (Comparable)o1;
			Comparable c2 = (Comparable)o2;
			return c1.compareTo(c2) * -1;
//			return c2.compareTo(c1);
		}
		return -1;	
		//비교대상이 Comparable을 구현한 클래스가 아니면 비교할 수 없기에 
		//참고로 String은 Comparator를 구현하지 않았다!! Comparable만!!!
	}
}

strArr = [Dog, cat, lion, tiger]
strArr = [cat, Dog, lion, tiger]
strArr = [tiger, lion, cat, Dog]
strArr = [tiger, lion, cat, Dog]


함수형 인터페이스

함수형 인터페이스타입의 매개변수

1.

  • 람다식이 있는 함수형인페(MyFunction)를 매개변수로 받는 메소드
  • 람다식에 이름을 붙여(myMethod()) 람다식을 호출하는 메소드(aMethod())를 만든다.

2.

  • 람다식을 호출하는 메소드의 매개변수에 람다식을 작성한다.

함수형 인터페이스타입의 반환타입

  • 람다식이 있는 함수형인페(MyFunction)가 반환타입인 메소드
  • 그 메소드(myMethod()) 안에서 반환타입에 람다식을 작성한다.


링크텍스트

ex14_01


public class Ex14_01 {

	public static void main(String[] args) {
		//1. 익명클래스로
		MyFunction f1 = new MyFunction() {
			@Override
			public void run() {
				System.out.println("f1.run!");
			}
		};
		f1.run();
		
		//2. 람다식으로
		MyFunction f2 = () -> System.out.println("f2.run!!");
		f2.run();
		
		//3. 함수형인페를 매개변수로 삼고, 람다식을 호출하는 메소드
		MyFunction f3 = () -> System.out.println("f3.run!!!");
		execute(f3);	//이 두줄을 줄이면
		execute(() -> System.out.println("f3.run!!!"));
		
		//4. 함수형인페가 반환타입, 람다식을 뱉어내는 메소드
		MyFunction f4 = getMyFunction();
		f4.run();
		//이렇게 바로도 된다!
		getMyFunction().run();
		

	}//main
	
	static void execute(MyFunction f) {
		f.run();	//람다식을 호출하는 메소드
	}
	
	static MyFunction getMyFunction() {
//		MyFunction f = () -> System.out.println("f4.run!!!!");
//		return f;
		return () -> System.out.println("f4.run!!!!");
	}

}

@FunctionalInterface
interface MyFunction{
	void run();
}

f1.run!
f2.run!!
f3.run!!!
f3.run!!!
f4.run!!!!
f4.run!!!!



Ref

0개의 댓글