람다식 (Lambda Expression)
함수(메서드)를 간단한 '식(expression)'으로 표현하는 방법
익명 함수(이름이 없는 함수, anonymous function)
- 함수와 메서드의 차이
- 근복적으로 동일. 함수는 일반적 용어, 메서드는 객체지향개념 용어
- 함수는 클래스에 독립적, 메서드는 클래스에 종속적
// 반환 값이 있는 경우
(int a, int b) -> a > b ? a : b
// 매개변수의 타입이 추론 가능하면 생략가능(대부분 경우 생략가능)
(a, b) -> a > b ? a : b
✔️ 함수형 인터페이스
단 하나의 추상 메서드만 선언된 인터페이스
- 함수형 인터페이스 타입의 참조변수로 람다식을 참조할 수 있음
MyFunction f = (a, b) -> a > b ? a : b;
int value = f.max(3, 5); // 실제로는 람다식 호출
예시
List<String> list = Arrays.asList("abc", "aaa", "bbb", "ccc", "aaa");
Collections.sort(list, (s1, s2) -> s2.compareTo(s1));
✔️ java.util.function 패키지
- 자주 사용되는 다양한 함수형 인터페이스 제공
함수형 인터페이스 | 메서드 | 설명 |
java.lang.Runnable | void run() | 매개변수 X, 반환값 X |
Supplier<T> | T get() -> T | 매개변수 X, 반환값 O |
Consumer<T> | T -> void accep(T t) | 매개변수 O, 반환값 X |
Function<T, R> | T -> R apply(T t) -> R | 일반적인 함수. 하나의 매개변수를 받아서 결과를 변환 |
Predicate<T> | T -> boolean test(T t) -> boolean | 조건식을 표현하는데 사용됨. 매개변수는 하나, 반환 타입은 boolean |
✔️ 메서드 참조(method reference)
하나의 메서드만 호출하는 람다식은 '메서드 참조'로 간단히 할 수 있다.
ClassName::method
Integer method(String s) {
return Integer.parseInt(s);
}
// 메서드 참조로 변경
Function<String, Integer> f = Integer::parseInt;
스트림 (Stream)
다양한 데이터 소스를 표준화된 방법으로 다루기 위한 것
- 데이터 소스
- 컬렉션 (List, Set, Map), 배열 -> Stream으로 표준화하고 나면 중간 연산, 최종 연산 방식은 같음
List<Integer> list = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream(); // 컬렉션
스트림 작업 순서
1. 스트림 만들기
2. 중간 연산 (0~n번)
- 연산 결과가 스트림인 연산. 반복적으로 적용가능
3. 최종 연산 (1번) -> 결과 얻기
- 연산 결과가 스트림이 아닌 연산. 단 한번만 적용가능 (스트림 요소를 소모)
스트림의 특징
- 스트림은 데이터 소스로부터 데이터를 읽기만할 뿐 변경하지 않는다. (원본은 변경하지 않는다.)
- 스트림은 Iterator처럼 일회용이다. (필요하면 다시 스트림을 생성해야 함.), 최종연산 하고 나면 닫힌다.
- 최종 연산 전까지 중간연산이 수행되지 않는다. = 지연된 연산
- 로또 번호 추출 (예시)
IntStream intStream = new Random().ints(1, 46); // 1~45범위의 무한 스트림
intStream.distinct().limit(6).sorted() // 중간 연산
.forEach(i -> System.out.print(i + ","));
- 스트림은 작업을 내부 반복으로 처리한다.
- 스트림의 작업을 병렬로 처리 = 병렬스트림
int sum = strStream.parallel() // 병렬 스트림으로 전환
.mapToInt(s -> s.length()).sum(); // 모든 문자열의 길이의 합
- 기본형 스트림 - IntStream, LongStream, DoubleStream
- 오토박싱 & 언박싱의 비효율이 제거됨. (스트림으로 작업하는데 성능을 높이고 싶을 때 사용하면 된다.)
- Stream<Integer> 대신 IntStream사용
✔️ 스트림 생성
컬렉션
- Collection인터페이스의 stream()으로 컬렉션을 스트림으로 변환
- Stream<E> stream()
intStream.forEach(System.out::print); // 스트림의 모든 요소 출력
배열
- Stream<T> Stream.of(T...values) : 가변인자
- Stream<T> Arrays.stream(T[] array)
- Stream<T> Arrays.stream(T[] array, int startInclusive, int endExclusive) : 배열의 일부
특정 범위의 정수
- IntStream IntStream.range(int begin, int end)
- IntStream IntStream.rangeClosed(int begin, int end)
정리
// 1. 컬렉션
List<Integer> list = Arrays.asList(1,2,3,4,5);
Stream<Integer> intStream = list.stream(); // 컬렉션
// 2. 배열
Stream<String> strStream = Stream.of("a","b","c"); // 가변인자
Stream<String> strStream = Stream.of(new String[]{"a","b","c"});
Stream<String> strStream = Arrays.stream(new String[]{"a","b","c"});
Stream<String> strStream = Arrays.stream(new String[]{"a","b","c"}, 0, 3);
// 3. 특정 범위 정수
IntStream IntStream.range(int begin, int end) // 1,2,3,4
IntStream IntStream.rangeClosed(int begin, int end) // 1,2,3,4,5
✔️ 스트림 중간 연산
✔️ 스트림 최종 연산
📌 Reference
- 남궁 선, 「자바의 정석」, 도우출판
반응형
'프로젝트 개발 기록 > [개발] java | spring' 카테고리의 다른 글
[Java] Mutable, Immutable, 방어적 복사, unmodifiableList (0) | 2023.05.02 |
---|---|
멀티 모듈, 그게 뭔데? 그거 어떻게 하는건데? 🧐 (0) | 2023.04.17 |
[Java] 코딩테스트 대비 정리 (2) (0) | 2022.11.07 |
[Java] 코딩테스트 대비 정리 (1) (0) | 2022.10.29 |
댓글