Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[모던 자바 인 액션] 10주차 #12

Open
jeongminkyo opened this issue Aug 31, 2023 · 2 comments
Open

[모던 자바 인 액션] 10주차 #12

jeongminkyo opened this issue Aug 31, 2023 · 2 comments
Assignees
Labels
SummerCoding 땅울림 여름코딩 스터디 모던 자바 인 액션

Comments

@jeongminkyo
Copy link

jeongminkyo commented Aug 31, 2023

스터디 날짜
2023.09.01 금 9:00-10:00

내용
챕터19. 함수형 프로그래밍 기법
챕터20. OOP와 FP의 조화: 자바와 스칼라의 비교
챕터21. 결론 그리고 자바의 미래

공유

최승위

이성온

정민교

@jeongminkyo
Copy link
Author

자바 8의 기능 리뷰

변화가 생긴 이유

  • 멀티코어 프로세서의 파워를 충분히 활용해야 한다는 점. 즉 코드를 병렬로 실행해야 더 빠르게 코드를 실행할 수 있다.

  • 간결하게 데이터 컬렉션을 다루는 추세. 간결하게 데이터 컬렉션을 처리하려면 불변값을 생산할 수 있는 불변 객체와 불변 컬렉션이 필요하다.

동작 파라미터화(람다와 메서드 참조)

apple -> apple.getWeight() > 150 // 람다 코드를 전달할 수 있다.
Apple::isHeavy // 기존 메서드의 메서드 참조를 전달할 수 있다.
  • 메서드로 전달되는 값(파라미터로 넘기는 동작)은 Function, Predicate, BiFunction등의 형식을 갖는다.
  • 메서드를 수신한 코드에서는 apply, test 등의 메서드를 동해 전달받은 코드를 실행할 수 있다.

스트림

기존 컬렉션에 filter, map 등의 메서드를 추가하지 않고 스트림을 만든 이유

  • 파이프라인으로 연결하기 불편함
  • 스트림은 스트림생성-중간연산-최종연산 연결하기 좋음
  • 쉬운 병렬처리(parallel(), 병렬스트림)

CompletableFuture 클래스

  • Future를 이용하면 여러 작업이 동시에 실행될 수 있도록 다른 스레드나 코어로 작업을 할당 가능.

  • 기존 작업에서 결과가 필요할 때는 get메서드를 호출해서 Future가 완료될 때까지 기다릴 수 있다.

  • CompletableFuture와 Future의 관계는 스트림과 컬렉션의 관계와 같다.

    • thenCompose, thenCombine, allOf등을 제공한다.
    • 공통 디자인 패턴을 위 메서드들을 통해 함수형 프로그래밍으로 간결하게 표현할 수 있다.

Optional 클래스

  • 값이 없을 때 에러를 발생시킬 수 있는 null 대신 정해진 데이터 형식을 제공할 수 있다.
  • map, filter, ifPresent 등 상황에 맞게 빈 값을 처리하기 위한 메서드를 제공한다.
  • 자바 9에서는 optional에 stream(), or(), ifPresentOrElse()등의 새로운 메서드가 추가.

Flow API

  • 자바 9에서 리액티브 스트림, 리액티브 당김 기반 역압력 프로토콜을 표준화했다.
  • Publisher, Subscriber, Subscription, Processor를 포함한다.

디폴트 메서드

  • 자바 8 이전에는 인터페이스에서 메서드 시그니처만 정의할 수 있었다.
  • 디폴트 메서드는 인터페이스에서 메서드의 기본 구현을 제공한다.
  • 인터페이스에 새로운 기능을 추가했을 때 기존의 모든 고객이 새로 추가된 기능을 구현하지 않을 수 있게 되면서 사용자는 인터페이스가 바뀌어도 신경쓸 필요가 없게 됨.

@so3500
Copy link
Contributor

so3500 commented Aug 31, 2023

💡 모던 자바 인 액션 > 19장 내용 정리 여러가지 함수형 프로그래밍 기법들

일급 함수 (fist-class function)

  • 일반값처럼 취급할 수 있는 함수
  • 인수로 전달하거나 결과로 반환하거나 자료구조에 저장가능
Function<String, Integer> strToInt = Integer::parseInt;

고차원 함수 (high-order function)

  • 하나 이상의 동작을 수행하는 함수
  • 하나 이상의 함수를 인수로 받고 함수를 결과로 반환
Comparator<Apple> c = compainrg(Apple::getWeight);

커링 (currying)

  • 함수를 모듈화하고 코드 재사용 시 사용하는 기법
  • x 와 y 두 인수를 받는 함수 f 를 한 개의 인수를 받는 g 라는 함수로 대체하는 기법
  • f(x,y) = (g(x))(y)

예시) 섭씨를 화씨로 변환

  • 매번 필요한 값을 각각 입력해야 하며 각 인수가 의미하는 것을 기억하고 있어야 함
// 섭씨를 화씨로 변환하는 예시 CtoF(x) = x*9/5 + 32
static double converter(double x, double f, double b) {
	return x * f + b;
}

double fTem = converter(30, 9/5, 32);
double krw = converter(1000, 1325, 0);

예시) 개선된 변환코드

  • 한 개의 인수를 갖는 변환 함수를 생산하는 팩토리를 정의하여 기존의 변환 로직을 재활용할 수 있음
static DoubleUnaryOperator curriedConverter(double f, double b) {
	return (double x) -> x * f + b;
}

// 사용예시
DoubleUnaryOperator convertCtoF = curriedConverter(9/5, 32);
double fTem = convertCtoF.applyAsDouble(30);

DoubleUnaryOperator convertUSDtoKRW = curriedConverter(1325, 0);
double krw = convertUSDtoKRW.applyAsDouble(1000);

영속 자료구조 (persistent data structure)

  • 함수형 프로그램에서는 함수형 자료구조, 불변 자료구조 등 용어도 사용하지만 보통은 영속 자료구조라고 부름 (데이터베이스의 영속과는 다른 의미)
  • 함수형 메서드에서는 전역 자료구조나 인수로 전달된 구조를 갱신할 수 없음. 자료구조를 바꾼다면
    • 같은 메서드를 두번 호출 시 결과가 달라지면서 참조 투명성에 위배되고
    • 인수를 결과로 단순하게 매핑 할 수 있는 능력이 상실

파괴적인 갱신과 함수형

  • 자료구조를 갱신할 때 발생할 수 있는 문제
// A에서 B까지 기차여행을 의미해는 가변 클래스
// 단방향 연결 리스트로 구현
class TrainJourney {
	public int price;
	public TrainJourney onward;
	public TrainJourney(int p, TrainJourney t) {
		price = p;
		onward = t;
	}
}
  • X → Y, Y → Z 여행을 나타내는 객체가 있을 때 두 객체를 연결하여 하나의 여행을 나타내기 (X → Y → Z)
  • link 의 문제점은 첫번째 인수로 주어진 객체의 종점이 변경된다는 것
  • 만약 첫번째 인수에 의존하는 코드가 있다면 그 코드도 영향을 받게 됨

image

// 자료구조가 파괴적으로 갱신됨
static TrainJourney link(TrainJourney a, TrainJourney b) {
	if (a == null) return b;
	TrainJourney t = a;
	while(t.onward != null) {
		t = t.onward;
	}
	t.onward = b;
	return a;
}
  • 함수형에서는 이 같은 부작용을 제한하는 방식으로 문제를 해결함
  • 계산 결과를 표현할 자료구조가 필요하면 기존의 자료구조를 갱신하지 않도록 새로운 자료구조를 만듦
// 자료구조가 갱신되지 않음
static TrainJourney append(TrainJourney a, TrainJourney b) {
	return a == null ? b : new TrainJourney(a.price, append(a.onward, b));
}

image

  • 이 코드는 함수형이며 기존 자료구조를 변경하지 않음 (하지만 TrainJourney 전체를 새로 만들진 않음)
  • 주의할 점은 사용자 역시 append 의 결과를 갱신하지 말아야 함
  • append 의 결과를 갱신하면 b로 전달된 정보도 바뀜

패턴 매칭

  • 한 개 이상의 파라미터에 대한 멀티 매칭 (정규 표현식과 관련된 매칭과는 다름)
  • 기존 자바에서는 패턴 매칭 대신 if-then-else 구문을 중첩하여 구현
  • 스칼라에서는 이미 패턴 매칭을 지원하고 있음
def simplifyExpression(expr: Expr): Expr = expr match {
	case BinOp("+", e, Number(0)) => e  // 0 더하기
	case BinOp("*", e, Number(1)) => e  // 1 곱하기
	case BinOp("/", e, Number(1)) => e  // 1 나누기
	case _ => expr                      // expr을 단순화할 수 없다
}
  • 최신 자바 21에서는 어디까지 발전했을까?
  • 1주차 내용 짚어보기 pattern matching for instanceof
// ASIS
if (obj instanceof String) {
    String t = (String) obj;
}

// TOBE
if (obj instanceof String t) {
 t.isEmtpy
}

[JEP 441: Pattern Matching for switch](https://openjdk.org/jeps/441)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
SummerCoding 땅울림 여름코딩 스터디 모던 자바 인 액션
Projects
None yet
Development

No branches or pull requests

3 participants