fastcampus 사이트의 'Java 웹 개발 마스터' ,유튜브 '어라운드 허브 스튜디오 - 람다함수'를 보고 공부 목적으로 정리 하였습니다.
▶ 람다함수란
프로그래밍 언어에서 사용되는 개념으로 익명함수(Anonymous Function)를 지칭하는 용어로 함수를 변수처럼 사용합니다. 따라서 클래스를 생성하지 않고 함수의 호출만으로 기능을 수행할 수 있습니다. 람다함수를 사용하는 것은 함수형 프로그래밍이라고 이야기합니다. 함수형 인터페이스를 선언하고 메소드를 구체화하여 사용합니다.
- JAVA 8버전 이상부터 지원
▶ 함수형 프로그래밍이란
람다함수는 추가 클래스를 생성하지 않고 함수의 호출만으로 기능을 수행하는 방식입니다.
- 순수함수를 구현하고 호출 → 부작용(sside-effect)가 없는 함수, 함수의 실행이 외부에 영향을 끼치지 않는다.
- 매개변수만을 사용하도록 만든 함수로 외부자료에 부수적인 영향이 발생하지 않도록 한다.
- 입력받은 자료를 바탕으로 수행되고 외부에 영향을 미치지 않으므로 병렬처리가 가능
- 안정적인 확장성있는 프로그래밍 방식
▶ 장점
- 코드의 라인 수가 줄어듦 → 메소드로 표현된 코드에 비해 확연히 라인 수가 줄어든다.
- 병렬 프로그래밍이 가능
- 람다식으로 바로 실행문을 전달할 수 있음(메소드 호출 필요 X)
- 코드가 간결해진다.
- 필요한 정보만을 사용함으로써 성능이 향상된다.(지연 연산 지원)
▶ 단점
- 람다식은 재사용이 불가능하다.(람다함수는 일회용 함수의 정의가 목적)
- 불필요하게 너무 많이 사용할 경우 가독성이 떨어진다.(같은 기능의 함수를 여러번 정의하는 경우)
- 디버깅시에 추적이 어렵다.
▶ 람다식의 문법
구조: (매개변수) -> {함수구현부} / ()->{함수구현}
1. 매개 변수가 하나인 경우 괄호 생략이 가능하다. (두개인 경우는 괄호 생략 불가)
str -> { System.out.println(str); } //str을 받으면 str을 출력하라
2. 중괄호 안의 구현부가 한 문장인 경우 중괄호 생략가능
str-> System.out.println(str);
3. 중괄호 안의 구현부가 한 문장이라도 return문은 중괄호를 생략할 수 없다.
str -> return str.length( ); X
str -> {return str.length( );} O
4. 중괄호 안의 구현부가 반환문 하나라면 return과 중괄호를 모두 생략할 수 있다.
(x, y) -> x + y //두 값을 더하여 반환
str -> str.length() //문자열 길이를 반환
▶ @FunctionalInterface 함수형 인터페이스
위의 어노테이션이 들어간 경우 '인터페이스 내부에 구현해야할 추상메소드는 하나만 쓸 수 있다' 라는 것을 명시합니다.
@FunctionalInterface
interface Print {
void print(int a, int b);
}
class Test {
public void testMethod(Print pr) {
pr.print(1, 2);
System.out.println("콘솔출력 실행문");
}
}
public class LambdaExample1 {
public static void main(String[] args) {
Test noLambda = new Test();
// 람다함수 사용X
noLambda.testMethod(new Print() {
@Override
public void print(int a, int b) {
System.out.println("a와 b의 합은 " + (a + b));
System.out.println("a와 b의 차는 " + (a - b));
}
});
//람다함수 사용O
Test lambdaTest = new Test();
lambdaTest.testMethod((a, b) -> {
System.out.println("a와 b의 합은 " + (a + b));
System.out.println("a와 b의 차는 " + (a - b));
});
}
}
<<Console>>
a와 b의 합은 3
a와 b의 차는 -1
콘솔 출력 실행문
a와 b의 합은 3
a와 b의 차는 -1
콘솔 출력 실행문
@FunctionalInterface
interface BigNumber {
int getBigNumber(int num1, int num2);
}
public class LambdaExample2 {
public static void main(String[] args) {
BigNumber bigNumber = (x, y) -> {
if(x > y) {
return x;
} else {
return y;
}
};
int result = bigNumber.getBigNumber(2156, 12382);
System.out.println(result);
}
}
<<Console>>
12382
import java.util.function.BinaryOperator;
import java.util.function.IntFunction;
public class JavaFunction {
public static void main(String[] args) {
//int 값을 매개변수로 받아 함수를 생성
IntFunction intSum = (a) -> a + 10;
System.out.println(intSum.apply(5));
//동일한 타입의 두 값을 받아 연산을 처리
BinaryOperator binarySum = (a, b) -> a + " " + b;
System.out.println(binarySum.apply(1, 2));
System.out.println(binarySum.apply("어라운드 허브", "스튜디오"));
}
}
<<Console>>
15
1 2
어라운드 허브 스튜디오
▶ 스트림(Stream)
- 자료의 대상과 관계없이 동일한 연산을 수행할 수 있는 기능(자료의 추상화)
- 배열, 컬렉션에 동일한 연산이 수행되어 일관성 있는 처리가능
- 한번 생성하고 사용한 스트림은 재사용할 수 없음
- 스트림 연산은 기존 자료를 변경하지 않음
- 중간연산과 최종연산으로 구분
- - 중간연산 : 특정 조건에 맞는 연산을 가져온다.
- - 최종연산 : 중간연산을 거친 후 최종 연산의 결과를 출력
- 최종연산이 수행되어야 모든 연산이 적용되는 지연연산
▶ 스트림 연산 - 중간연산
- filter() : 조건에 맞는 요소를 추출
- map() : 요소를 반환
ex)
1. 문자열의 길이가 5 이상인 요소만 출력하기
→ sList.stream().filter(s->s.length() >= 5).forEach(s->System.out.println(s));
스트림 생성 중간연산 최종연산
2. 고객 클래스에서 고객이름만 가져오기
→ customerList.stream().map(c->c.getName()).forEach(s->System.out.println(s));
▶ 스트림 연산 - 최종연산
- 스트림의 자료를 소모하면서 연산을 수행
- 최종연산 후에 스트림은 더 이상 다른 연산을 적용할 수 없음
- forEach() : 요소를 하나씩 꺼내옴
- count() : 요소의 개수
- sum() : 요소의 합
- 이외에도 여러가지 연산이 있다.
▶ reduce() 연산
- 정의된 연산이 아닌 프로그래머가 직접 지정하는 연산을 적용
- 최종연산으로 스트림의 요소를 소모하며 연산수행
- 배열의 모든 요소의 합을 구하는 reduce()연산
<예제1 >
int[] arr = {1,2,3,4,5};
int sum = Arrays.stream(arr).sum();
int count = (int)Arrays.stream(arr).count();
System.out.println(sum); //15
System.out.println(count); //5
System.out.println(Arrays.stream(arr).reduce(0, (a, b) -> a + b)); //15
<예제2 >
List<String> sList = newArrayList<String>();
sList.add("Tomas");
sList.add("Edward");
sList.add("Jack");
Stream<String> stream = sList.stream();
stream.forEach(s->System.out.print( s + " ")); // Tomas Edward Jack
System.out.println();
sList.stream().sorted().forEach(s->System.out.print( s + " ")); // Edward Jack Tomas
System.out.println();
sList.stream().map(s->s.length()).forEach(n->System.out.print( n + " ")); // 5 6 4
<예제3 >
import java.util.Arrays;
import java.util.function.BinaryOperator;
class CompareString implements BinaryOperator<String> {
@Override
public String apply(String s1, String s2) {
if(s1.getBytes().length >= s2.getBytes().length)
return s1;
else
return s2;
}
}
public class ReduceTest {
public static void main(String [] args) {
String[] greetings = {"안녕하세요~~~", "hello", "Good morning", "반갑습니다"};
System.out.println(Arrays.stream(greetings).reduce("",(s1, s2)->
{ if(s1.getBytes().length >= s2.getBytes.length)
return s1;
else return s2;
})); // 안녕하세요~~~
System.out.println(Arrays.stream(greetings).reduce(new CompareString()).get()); // 안녕하세요~~~
'Spring' 카테고리의 다른 글
6. 스프링 Servlet (0) | 2022.07.02 |
---|---|
5. 스프링 AOP (0) | 2022.06.28 |
3. 템플릿 메소드 패턴 VS 전략패턴 (0) | 2022.01.12 |
2. 토비 Chapter 4.템플릿 내용 정리 (0) | 2022.01.09 |
1. Spring annotation (0) | 2021.12.30 |