아래 블로그 내용 정리
함수형 프로그래밍 기초 (1) 왜 함수형 프로그래밍인가
[JAVA 8] - 함수형 프로그래밍(Functional Programming)
객체 지향 프로그래밍과 함수형 프로그래밍의 차이
간결하게 코드를 작성할 수 있고, 객체 지향과 다른 방식으로 접근해야 한다.
함수형프로그래밍은 몇몇 자료구조(list, set, map)을 이용해 최적화된 동작을 만든다
위 블로그에서 예제 코드를 보았는데 이해가 안가서 스트림과 람다에 대해 학습해야할 것 같다.
부수 효과를 없애고 순수 함수를 만들어 모듈화 수준을 높이는 프로그래밍 패러다임
List<String> myList = Arrays.asList("c1", "a2", "b3", "4", "5");
// 기존 방식
for(int i = 0; i < myList.size(); i++){
String s = myList.get(i);
if(s.startsWith("c")){
System.out.println(s.toUpperCase());
}
}
// stream API를 이용한 방식
myList.stream()
.filter(s -> s.startsWith("c"))
.map(String::toUpperCase)
.forEach(System.out::println);
1급 객체란 다음 조건을 만족하는 객체이다.
함수형 프로그래밍은 코드의 간결성이 증가 되었다.
블로그에 있는 예제코드들을 이해하기 위해서 람다식과 스트림에 대한 이해가 필요하다고 생각해서 자바의 정석 ch14 람다와 스트림 파트를 학습하였다.
함수형 인터페이스는 단 하나의 추상 메서드만 가질 수 있다.
람다식은 익명객체이기 때문에 람다식을 다루기 위해서는 참조 변수가 필요하다.
이 참조 변수의 타입은 함수형 인터페이스로 한다.
단, 함수형 인터페이스의 메서드와 람다식의 매개변수 개수와 반환타입이 일치해야한다.
아래의 두 코드를 잘 비교해보자.
interface MyFunction {
int max (int a, int b);
}
public class Exam {
// MyFunction 인터페이스를 구현한 익명 객체 생성
MyFunction f = new MyFunction() {
public int max(int a, int b) {
return a > b ? a : b;
}
};
int value = f.max(5, 3); // 익명 객체의 메서드를 호출
}
위의 코드는 MyFunction 인터페이스를 정의하고, 이 인터페이스를 구현한 익명 클래스의 객체를 생성한 것이다.
위의 코드를 람다식을 이용하여 아래와 같이 바꿀 수 있다.
@FunctionalInterface
interface MyFunction {
int max (int a, int b);
}
public class Exam {
MyFunction f = (a, b) -> a > b ? a : b;
int value = f.max(3, 5);
}
코드가 훨씬 간결해졌다.
람다식은 익명 객체이다.
@FuncionalInterface 어노테이션을 추가해주면 알아서 컴파일러가 함수형 인터페이스 조건에 맞는지 검사해준다.
MyFunction 타입의 참조변수 f는 람다식을 다루기 위한 참조변수 이다.
@FunctionalInterface
interface MyFunction {
void run();
}
class LamdaEx1 {
// 매개변수 타입이 MyFunction(함수형 인터페이스)인 메서드
static void execute(MyFunction f) {
f.run();
}
// 반환타입이 MyFunction(함수형 인터페이스)인 메서드
static MyFunction getMyFunction() {
return () -> System.out.println("f2.run()");
}
public static void main(String[] args) {
// 람다식으로 MyFunction의 run() 구현
MyFunction f1 = () -> System.out.println("f1.run()");
MyFunction f2 = getMyFunction();
f1.run();
f2.run();
System.out.println();
execute(f1);
execute(() -> System.out.println("run"));
}
}
</> 실행 결과
f1.run()
f2.run()
f1.run()
run
static void execute(MyFunction f) {
f.run();
}
static MyFunction getMyFunction() {
return () -> System.out.println("f2.run()");
}
MyFunction f1 = () -> System.out.println("f1.run()");
execute(() -> System.out.println("run"));
java.util.function 패키지에 자주 쓰이는 형식의 메서드를 함수형 인터페이스로 정의해놓음
Predicate<String> isEmptyStr = s -> s.length() == 0;
String s = "";
if(isEmptyStr.test(s)){
System.out.println("This is an empty String.");
}
아래 블로그 보고 학습 정리
정리가 굉장히 잘되어 있는 것 같다.
1) 스트림이란?
데이터의 흐름으로 배열 또는 컬렉션 인스턴스에 함수를 조합하여 원하는 결과를 필터링하고 가공된 결과를 손쉽게 처리 가능
기존 방식을 이용한 출력
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class StreamExam {
public static void main(String[] args) {
String[] strArr = {"data1", "data2", "data3"};
List<String> strList = Arrays.asList(strArr);
// 기존 방식, for문을 이용해 결과 출력
Arrays.sort(strArr);
Collections.sort(strList);
for(String str : strArr){
System.out.println(str);
}
for(String str : strList) {
System.out.println(str);
}
}
}
Stream API 사용
// Stream API 사용
strList.stream().sorted().forEach(System.out::println);
Arrays.stream(strArr).sorted().forEach(System.out::println);
// 람다식으로 표현
strList.stream().sorted().forEach(x -> System.out.println(x));
Arrays.stream(strArr).sorted().forEach(x -> System.out.println(x));
데이터 소스(배열 혹은 리스트)로 부터 스트림을 생성하고,
정렬을 위해 sorted()메서드를 호출하고,
출력을 위해 forEach()메서드 호출
수고하셨습니다. 공부한 양이 엄청 많네요!