11 람다식과 함수형 프로그래밍
람다식(Lambda Expression)
람다식(Lambda Expression)은 자바 8(Java 8)부터 도입된 기능으로, 자바에서 함수형 프로그래밍을 지원하기 위한 방식입니다.
람다식을 사용하면 간결하게 코드를 작성할 수 있으며, 특히 익명 클래스나 함수형 인터페이스를 구현할 때 유용합니다. 람다식은 메소드의 간결한 표현이자, 익명 메소드를 만드는 데 사용됩니다.
람다식의 기본 구조
람다식의 기본적인 문법은 다음과 같습니다.
혹은 여러 줄의 코드를 포함할 경우.
람다식의 구성 요소
매개변수 목록
(parameters)
: 메소드에 전달되는 인자 목록과 동일합니다. 여러 개의 인수가 있을 수 있으며, 인수가 없을 때는 빈 괄호()
를 사용합니다.화살표 연산자
->
: 매개변수와 람다식의 본문을 구분하는 역할을 합니다.람다식의 본문
expression
: 람다식이 수행할 작업을 정의합니다. 한 줄의 표현식이나 여러 줄의 블록으로 구성될 수 있습니다.
함수형 인터페이스
람다식을 사용하려면 함수형 인터페이스가 필요합니다.
함수형 인터페이스는 추상 메소드가 단 하나만 있는 인터페이스를 말합니다.
자바 8에서는 이러한 인터페이스를 쉽게 구분할 수 있도록 @FunctionalInterface 어노테이션을 제공하고 있습니다.
함수형 인터페이스 예시1
edu.ch11.interfaceExample 패키지
이제 이 인터페이스를 람다식을 통해 구현할 수 있습니다:
함수형 인터페이스 예시2
edu.ch11.interfaceExample 패키지
java.util.function 패키지
자바는 람다식을 위한 함수형 인터페이스가 정의되어 있어야 해사, 필요할 때마다 정의해야 하므로 번거로움이 있습니다.
자주 사용하는 인터페이스가 java.util.function
패키지에 제공합니다.
Runnable
(java.lang
패키지)
run
Supplier<T>
get
T
Consumer<T>
accept
T
BiConsumer<T, U>
accept
T
, U
Function<T, R>
apply
T
R
BiFunction<T, U, R>
apply
T
, U
R
Predicate<T>
test
T
boolean
BiPredicate<T, U>
test
T
, U
boolean
UnaryOperator<T>
apply
T
T
BinaryOperator<T>
apply
T
, T
T
(T 와 U는 서로 다른 자료형을 받을 수 있다는 것을 의미하며 같아도 상관없음)
Runnable
Runnable
메소드 이름:
run
인자 타입: 없음
반환값 타입: 없음
설명: 매개변수를 받지 않고 아무 값도 반환하지 않는 함수형 인터페이스입니다. 일반적으로 스레드를 실행할 때 사용됩니다.
바로 실행하는 로직
실행 결과:
Supplier<T>
Supplier<T>
메소드 이름:
get
인자 타입: 없음
반환값 타입:
T
설명: 입력 매개변수 없이 값을 반환하는 함수형 인터페이스입니다. 값을 공급하는 역할을 합니다.
Consumer<T>
Consumer<T>
메소드 이름:
accept
인자 타입:
T
반환값 타입: 없음
설명: 입력된 매개변수(
T
)를 받아서 처리하고, 결과를 반환하지 않는 함수형 인터페이스입니다.
BiConsumer<T, U>
BiConsumer<T, U>
메소드 이름:
accept
인자 타입:
T
,U
반환값 타입: 없음
설명: 두 개의 매개변수(
T
,U
)를 받아서 처리하고, 결과를 반환하지 않는 함수형 인터페이스입니다.
Function<T, R>
Function<T, R>
메소드 이름:
apply
인자 타입:
T
반환값 타입:
R
설명: 입력값(
T
)을 받아서, 결과값(R
)을 반환하는 함수형 인터페이스입니다. 주로 입력을 변환하여 출력하는 역할을 합니다.
BiFunction<T, U, R>
BiFunction<T, U, R>
메소드 이름:
apply
인자 타입:
T
,U
반환값 타입:
R
설명: 두 개의 입력값(
T
,U
)을 받아서, 결과값(R
)을 반환하는 함수형 인터페이스입니다.
Predicate<T>
Predicate<T>
메소드 이름:
test
인자 타입:
T
반환값 타입:
boolean
설명: 입력값을 받아 조건을 검사하여 참 또는 거짓을 반환하는 함수형 인터페이스입니다.
BiPredicate<T, U>
BiPredicate<T, U>
메소드 이름:
test
인자 타입:
T
,U
반환값 타입:
boolean
설명: 두 개의 입력값을 받아 조건을 검사하여 참 또는 거짓을 반환하는 함수형 인터페이스입니다.
UnaryOperator<T>
UnaryOperator<T>
메소드 이름:
apply
인자 타입:
T
반환값 타입:
T
설명: 동일한 타입의 값을 입력받아 같은 타입의 값을 반환하는 함수형 인터페이스입니다.
Function<T, R>
의 특수한 형태로, 입력과 출력 타입이 동일할 때 사용합니다.
BinaryOperator<T>
BinaryOperator<T>
메소드 이름:
apply
인자 타입:
T
,T
반환값 타입:
T
설명: 두 개의 동일한 타입의 값을 입력받아 같은 타입의 값을 반환하는 함수형 인터페이스입니다.
BiFunction<T, U, R>
의 특수한 형태로, 두 입력값과 결과값이 모두 같은 타입일 때 사용합니다.
메소드 참조(Method reference)
람다식이 어떤 메소드 하나만 호출할 때(해당 람다식과 메소드의 의미가 사실상 같을 때) 코드를 간편화하는 방법입니다.
클래스 메소드 호출
설명: 클래스의 정적 메소드(static method)를 참조할 때 사용합니다.
예시:
Integer
클래스의parseInt
메소드를 참조하는 예시.
edu.ch11.methodReference 패키지
인스턴스 메소드 호출
(1) 특정 클래스의 인스턴스 메소드 참조
설명: 클래스의 인스턴스 메소드를 참조할 때 사용합니다. 이 경우 첫 번째 매개변수는 해당 클래스의 인스턴스가 됩니다.
예시:
String
클래스의toUpperCase
메소드를 참조하는 예시.
edu.ch11.methodReference 패키지
(2) 특정 인스턴스의 인스턴스 메소드 참조
설명: 특정 인스턴스의 메소드를 참조할 때 사용합니다.
예시: 특정
Example
인스턴스의 메소드를 참조하는 예시.
edu.ch11.methodReference 패키지
3. 클래스 생성자 호출
설명: 해당 클래스의 생성자를 참조하여 객체를 생성할 때 사용합니다.
예시:
Person
객체를 생성하는 생성자 참조 예시.
edu.ch11.methodReference 패키지
정리
클래스 메소드 호출:
{클래스명}::{클래스 메소드명}
을 사용하여 정적 메소드를 참조할 수 있습니다.인스턴스 메소드 호출:
특정 클래스의 인스턴스 메소드를 참조하려면
{클래스명}::{인스턴스메소드명}
을 사용합니다.특정 인스턴스의 메소드를 참조하려면
{인스턴스}::{인스턴스메소드명}
을 사용합니다.
생성자 호출:
{클래스}::new
를 사용하여 생성자를 참조하고 객체를 생성할 수 있습니다.
메소드 참조를 사용하면 람다식을 더욱 간결하고 가독성 좋게 표현할 수 있습니다.
스트림(Stream)과 스트림 연산(Stream Operations)
스트림(Stream)은 자바 8(Java 8)에서 도입된 기능으로, 컬렉션이나 배열의 요소를 처리하는 선언적이고 간결한 방법을 제공합니다.
스트림을 통해 데이터의 필터링, 매핑, 정렬, 집계 등의 다양한 연산을 할 수 있으며, 이를 스트림 연산(Stream Operations)이라고 합니다.
1. 스트림이란?
데이터의 연속적인 흐름: 스트림은 컬렉션, 배열 등의 데이터를 다루기 위한 데이터의 연속적인 흐름입니다.
데이터 소스로부터 추상화: 스트림은 데이터 소스(예: 컬렉션, 배열)로부터 데이터를 추상화하여 처리할 수 있습니다.
한 번만 소비 가능: 스트림은 일회용이며, 한 번 사용한 스트림은 재사용할 수 없습니다.
데이터를 변경하지 않음: 스트림은 원본 데이터를 변경하지 않고, 데이터의 복사본을 처리합니다.
지연 연산: 스트림 연산은 지연 평가(Lazy Evaluation) 방식을 사용하여 필요한 때까지 연산을 수행하지 않습니다.
2. 스트림 연산의 종류
스트림 연산은 크게 중간 연산과 최종 연산으로 나눌 수 있습니다.
중간 연산: 스트림을 가공하여 새로운 스트림을 반환하는 연산입니다. 여러 개의 중간 연산을 체인(chain)으로 연결할 수 있습니다. 예를 들어,
filter()
,map()
,sorted()
등이 중간 연산에 해당합니다.최종 연산: 스트림을 소비하여 결과를 반환하는 연산입니다. 최종 연산이 호출되면 스트림이 종료되고 더 이상 사용할 수 없습니다. 예를 들어,
forEach()
,collect()
,reduce()
등이 최종 연산에 해당합니다.
3. 스트림 생성
스트림은 다양한 소스(배열, 값, 컬렉션, 빌더, concat 메소드 등)로부터 생성할 수 있습니다. 대표적으로 컬렉션이나 배열에서 스트림을 생성하는 방법은 다음과 같습니다:
컬렉션에서 스트림 생성:
edu.ch11.stream 패키지
배열에서 스트림 생성:
edu.ch11.stream 패키지
4. 중간 연산 예시
1. filter(Predicate)
filter(Predicate)
요소를 걸러내는 연산으로, 조건에 맞는 요소만 포함하는 새로운 스트림을 반환합니다.
edu.ch11.streamOperations 패키지
2. map(Function)
map(Function)
각 요소를 주어진 함수에 의해 매핑하여 새로운 요소로 변환하는 연산입니다.
edu.ch11.streamOperations 패키지
3. sorted()
sorted()
스트림의 요소를 정렬하는 연산입니다.
edu.ch11.streamOperations 패키지
4. distinct()
distinct()
스트림의 요소 중 중복된 요소를 제거합니다.
edu.ch11.streamOperations 패키지
5. 최종 연산 예시
1. forEach(Consumer)
forEach(Consumer)
각 요소에 대해 주어진 동작을 수행하는 연산입니다.
edu.ch11.streamOperations 패키지
2. collect()
collect()
스트림의 요소를 컬렉션으로 수집하는 연산입니다. 주로
Collectors
유틸리티 클래스를 함께 사용합니다.
edu.ch11.streamOperations 패키지
3. reduce()
reduce()
스트림의 모든 요소를 결합하여 하나의 값을 생성하는 연산입니다.
edu.ch11.streamOperations 패키지
6. 스트림의 특징: 지연 연산
지연 연산(Lazy Evaluation): 스트림의 중간 연산은 최종 연산이 호출될 때까지 실제로 수행되지 않습니다. 이로 인해 불필요한 연산을 방지하고, 성능을 최적화할 수 있습니다.
정리
스트림(Stream)은 자바의 컬렉션, 배열 등의 요소를 효율적으로 처리하기 위한 기능으로, 데이터의 필터링, 매핑, 정렬, 집계 등의 다양한 연산을 제공합니다.
스트림 연산은 중간 연산과 최종 연산으로 나뉘며, 중간 연산은 새로운 스트림을 반환하고 최종 연산은 스트림을 소비하여 결과를 반환합니다.
Last updated