자바에서 람다는 기존의 인터페이스형태의 클래스를 화살표모양의 함수 형태로 표기하는 방법 입니다.
이러한 람다식의 장점은 아래와 같습니다.
1. 코드의 간결성 - 람다를 사용하면 불필요한 반복문의 삭제가 가능하며 복잡한 식을 단순하게 표현할 수 있습니다.
2. 지연연산 수행 - 람다는 지연연상을 수행 함으로써 불필요한 연산을 최소화 할 수 있습니다.
3. 병렬처리 가능 - 멀티쓰레디를 활용하여 병렬처리를 사용 할 수 있습니다.
일반적으로 표기하는 람다식 샘플 입니다.
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class LambdaTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.stream().map( arg -> arg*2).forEach(System.out::println);
}
}
스트림(stream) 객체에서 map 메소드를 실행 하였습니다.
map은 스트림 객체의 값을 변화시킬 때 사용하는 메소드 입니다.
이와같은 람다식을 쓰지 않고 자바7 이하의 버전으로 표기하려면 아래처럼 해야 합니다.
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class LambdaTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.stream().map( arg -> arg*2).forEach(System.out::println);
//자바7 이하로 표기
list.stream().map( new Function<Integer, Integer>() { //map람다를 풀어썼습니다.
@Override
public Integer apply(Integer t) {
return t * 2;
}
}).forEach(new Consumer<Integer>() { //foreach에서의 이중콜른 표기법을 풀어 썼습니다.
@Override
public void accept(Integer t) {
System.out.println(t);
}
});
}
}
코드가 딸랑 2줄인 내용이 위 샘플코드처럼 방대해진 것을 볼 수 있습니다.
이러한 람다식은 화살표 모양으로도 사용할 수 있으면서, 메소드 형태로 분리하여 대입하는 방법으로도 사용 할 수 있습니다.
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class LambdaTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.stream().map( testMethod(aaa->aaa)).forEach(System.out::println);
}
public static Function<Integer,Integer> testMethod(Function<Integer, Integer> fun){
return arg ->{
return fun.apply(arg) * 2; //위 map 객체의 람다식을 메소드로 추가 정의하여 반환합니다.
};
}
}
map객체에서의 람다식을 testMethod 라는 메소드에서 받아서 다시 람다식으로 리턴하는 모습 입니다.
Function으로 반환한 이유는, map객체에서의 인자값은 Function으로 되어 있습니다.
그런데 이러한 메소드로 람다식을 다시 정의하는 방법은 조금 주의해야되는 점이 있습니다.
위 메소드를 간단하게 고쳐보겠습니다.
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
public class LambdaTest {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5);
list.stream().map( testMethod(aaa->aaa)).forEach(System.out::println);
}
public static Function<Integer,Integer> testMethod(Function<Integer, Integer> fun){
int number[] = {2};
return arg ->{
return fun.apply(arg) * number[0]++;
};
}
}
위 코드를 실행하면 몇몇 사람들이 "2, 4, 6, 8, 10" 이 출력될꺼야 라고 생각합니다.
왜냐하면 testMethod 메소드가 map 메소드에서 호출 될 때 마다 실행되는 것이라고 생각하기 때문에 number배열의 값은 항상 2로 초기화되어 존재할 것이라 생각 할 수 있기 때문 입니다.
그런데 이를 실행하면 아래와 같은 모습이 나옵니다.
무슨 상황인지 파악하기 위해서 간단한 출력코드를 입력 해 봅니다.
testMethod는 계속되서 사용되지 않았습니다.
testMethod에서 리턴한 함수식만 리스트의 크기에 맞게 map 메소드에 의해서 사용되는 것을 볼 수 있습니다.
이처럼 람다식을 사용할 때 메소드에 의해서 다시 함수로 리턴하는 방법은 메소드 영역의 변수들이 마치 공유 되듯 사용되는 것을 볼 수 있습니다.
이를 응용하면 아래 포스팅처럼 List형태의 값에서 데이터 중복제거하는 방법을 적용 할 수 있습니다.
https://lts0606.tistory.com/180
공부 할수록, 알면 알 수록 어렵고 재밌는 람다!
좀더 햇갈리지 않도록 열심히 노력해야겠습니다.
'Java(자바) > Java 기본' 카테고리의 다른 글
Java List Map 객체 정렬하기 (0) | 2022.09.05 |
---|---|
Mybatis jdbctype(마이바티스 Jdbctype) (0) | 2022.07.18 |
자바 참조 데이터(Java Array, Java List) 사용간 유의 사항 (0) | 2022.03.21 |
자바로 살펴본 재귀 함수의 동작 방법 - 2 (Java Recursive method with 순열) (2) | 2021.07.28 |
자바로 살펴본 재귀 함수의 동작 방법 - 1 (Java Recursive method) (2) | 2021.07.27 |
댓글