STREAM Set up
Java :
- version 8 이상
IDE :
- Eclipse 4.6 버전에서 JRE/JDK Version 8이상이 요구되므로 4.6이상 설치
- IntelliJ 모든 버전에서 JVM17 필요, 버전에 크게 상관 없어보임.
STREAM 사용을 위한 기초 개념
1. 명령형 프로그래밍(HOW) vs 선언형 프로그래밍(WHAT)
- 명령형 프로그래밍 (HOW)
EX) 짝수 홀수 구분
public int[] solution(int[] num_list) {
// 짝수 개수와 홀수 개수를 세서 담을 int 배열을 선언한다.
int[] answer = new int [2];
int a = 0;
int b = 0;
// 배열의 값을 하나씩 2로 나누어 나머지를 확인해 짝수, 홀수를 판별한다.
for(int i = 0; i<num_list.length; i++) {
if(num_list[i]%2==0) {
a ++;
} else {
b ++;
}
}
// 짝수의 개수는 0번 인덱스에, 홀수개수는 1번인덱스에 저장한다.
answer[0] = a;
answer[1] =b;
return answer;
}
명령형 프로그래밍 : 문제를 해결하는 방법을 고민
1. 결과값을 담을 int 배열을 만든다.
2. for 문으로 짝수, 홀수를 분류한다.
3. 결과 배열에 짝수, 홀수를 넣어준다.
와 같은 무엇을 할 지를 위주로 프로그래밍한다.
- 선언형 프로그래밍(WHAT)
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class example {
public static void main(String[] args) {
// 테스트 케이스를 위한 데이터
number number1 = new number()
.setNumber(1);
number number2 = new number()
.setNumber(2);
number number3 = new number()
.setNumber(3);
number number4 = new number()
.setNumber(4);
List<number> Numbers = new ArrayList<>();
Numbers.add(number1);
Numbers.add(number2);
Numbers.add(number3);
Numbers.add(number4);
// --------------------------------------------------------
// 배열을 받아 짝수만 filtering하여 돌려주는 함수
List<Integer> evenNumber = Numbers.stream()
.filter(number -> number.getNumber()%2 == 0)
.map(number::getNumber)
.collect(Collectors.toList());
// 짝수만 담긴 리스트의 개수를 출력한다.
System.out.println(evenNumber.size());
}
}
선언형 프로그래밍 : 문제 해결 방법을 고민
1. 주어진 숫자 리스트에서 짝수만 골라 리스트로 받는다. = 짝수만 filtering하는 함수를 만든다.
-> 위 예시가 간단하여 크게 차이가 느껴지지 않지만 생각하는 과정 자체가 3단계에서 1단계로
간단해짐을 알 수 있다. 다른 관련 게시글들을 살펴보면 추상화가 가능하기 때문이라고 설명한다.
https://iborymagic.tistory.com/73
2. 함수형 프로그래밍
- 자료처리를 수학적 함수의 계산으로 취급하고, 상태와 가변 데이터를 멀리하는 프로그래밍
결과적으로 함수를 Object의 형태로 나타내어 프로그래밍 하는 방법을 말한다.
Java 객체를 사용하는 경우, 객체의 필드나 변수 값, 상태를 변경하며 문제를 해결하는 코드를 작성하게 되는데
이러한 방식의 코드를 작성하는 것이 아니라
어떠한 값, 상태를 넣더라도 동일한 프로세스 (계산)을 거쳐 동일한 절차(계산식)를 따른 값을 반환하여
f(x) = y 라는 방정식이 성립 될 수 있도록 하는 방식이다.
- Stream 과 함수형 인터페이스를 같이 알아야 하는 이유
함수형 프로그래밍은 객체지향 언어의 개념에 더해 추가적인 방향성을 제시해 주며
Stream은 함수형 프로그래밍을 구현할 수 있게 해주는 도구이기 때문.
3. Lambda Expression (람다식)
3-1. Functional Interface
- 함수형 인터페이스는 추상 메소드 하나만 존재한다
- Functional Interface는 @FunctionalInterface 어노테이션을 사용하며 함수형인터페이스 조건에 맞는지 검사
- 추상 메소드는 해당 메소드를 구현하는 클래스에서 오버라이딩해서 사용해야하는 메소드이다.
- 이러한 특성이 람다로 표현된 익명 함수를 함수형 인터페이스의 인스턴스로 사용하여 구현이 가능해진다.
(Functional Interface의 apply 메소드를 수정하지 않고 구현하는 클래스에서 apply 메소드를 수정해서 사용이 가능해진다)
java.util.function 패키지 아래의 Interface Function<T,R>
Input은 T, result 는 R이다.
해당 인터페이스를 사용하여 함수를 구현하고
apply 메소드를 사용해 실행 가능하다.
https://docs.oracle.com/javase/8/docs/api/index.html

Functional Interface 추상 메소드를 구현하여 사용하기
- Functional Interface를 구현한 객체를 만들어 사용하기
multiplyOneHundredcalculator 라는 객체에 Function을 구현하게 하여 apply method override
import java.util.function.Function;
public class multiplyOneHundredcalculator implements Function <Integer,Integer>{
@Override
public Integer apply(Integer integer) {
return integer * 100;
}
}
import java.util.function.Function;
public class functionalInterfaceExample {
public static void main(String[] args) {
Function<Integer, Integer> calculator = new multiplyOneHundredcalculator();
int result = calculator.apply(100);
System.out.println(result); // 10000
}
}
apply 메소드를 multiplyOneHundredcalculator객체에서 override 했으므로 * 100 이 된 값이 출력된다.
Functional Interface를 람다 표현식을 사용하여 구현하기
- 람다 표현식 사용하기
multiplyOneHundredcalculator 를 사용하여 구현했던 apply 메소드를 람다 표현식을 사용하여 구현
import java.util.function.Function;
public class functionalInterfaceExample {
public static void main(String[] args) {
Function<Integer, Integer> calculator = (Integer x) -> {
return x * 100;
};
System.out.println(calculator.apply(100)); // 10000
}
}
-> 람다 표현식을 생략하여 구현
- 생략 조건
- calculator 선언 시 <> 내에 Integer를 선언해주었으므로 구현되는 부분의 (Integer x) 의 Integer 생략 가능
- 매개변수가 하나이므로 (x) 에서 () 생략 가능
- 바로 리턴값을 전달하므로 {} 생략 가능
import java.util.function.Function;
public class functionalInterfaceExample {
public static void main(String[] args) {
Function<Integer, Integer> calculator = (Integer x) -> {
return x * 100;
};
Function<Integer, Integer> calculator2 = x -> x * 100;
System.out.println(calculator.apply(100));
System.out.println(calculator2.apply(100));
}
}