[JAVA] Stream API (feat. 람다식, 함수형 인터페이스)

SCY·2023년 1월 31일
0

자바의 람다식을 검색하기 시작했더니 어느새 Stream API를 공부하고 있었다.
이왕 공부하는 김에 같이 알아보자.

Stream API

자바8부터 지원되며 순차적인 계산 처리(함수형 프로그래밍)가 가능하다.
데이터를 추상화하고 처리하는 데 자주 사용되는 함수들이 정의되어있다.

Stream의 효력을 알아보기 위해 코드 전후를 비교해보자.

String[] nameArr = {"MinSu", "SuJin", "ChunSik", "YoungJa"};
List<String> nameList = Arrays.asList(nameArr);

위 정의된 배열과 리스트를 정렬해보자.

  • Stream 사용 전

    Arrays.sort(nameArr);
    Collections.sort(nameList);
    
    for (String str : nameArr) {
        System.out.println(str);
    }
    for (String str : nameList) {
        System.out.println(str);
    }

    원본의 데이터가 직접 정렬된다.

  • Stream 사용 후

    Stream<String> nameStream = nameList.stream();
    Stream<String> arrayStream = Arrays.stream(nameArr);
    
    nameStream.sorted().forEach(System.out::println);
    arrayStream.sorted().forEach(System.out::println);

    복사된 데이터를 정렬한다. 훨씬 간결하고 가독성이 높다.

특징

  • 원본의 데이터를 변경하지 않음
  • 일회용 (한 번 사용하면 끝)
  • 내부 반복으로 작업을 처리함 (ex. forEach())

연산 과정

myList
	.stream() //생성하기
	.filter(member -> member.getName().equals(name)) //가공하기
	.findAny(); //결과만들기

위와 같이 생성 - 가공 - 결과의 연산 과정을 거친다.

  1. 생성 - 닫히면 다시 만들어주어야 함
  2. 가공 - 반환값이 모두 Stream이기에 연산 간의 연결이 가능
  3. 결과 - Stream의 요소를 소모하며 진행되므로 1번만 가능

자세한 내용은 다음 글에 포스팅.


Stream API를 공부할 때 알아두면 좋은
lambda와 함수형 인터페이스에 대해 간단히 짚어보자.

람다식 (lambda expression)

람다식은 함수를 하나의 식으로 표현한 것이다.
함수의 이름이 필요 없어 익명 함수로 생각할 수 있다.

파이선에서는 람다 함수를 lambda라는 문자 그대로 사용했는데
자바에서는 () -> {} 방식을 사용한다.

public String hello() {
    return "Hello World!";
}

() -> "Hello World!"; // lambda expression

위 두 코드는 같은 기능을 수행한다.
람다식 사용 시 코드가 간결해져 가독성이 높아진다.
하지만 재사용이 불가능하고 남발하면 코드가 지저분해질 수 있다.

함수형 인터페이스 (functional interface)

함수를 변수처럼 선언 가능하다.

public class Lambda {
	public static void main(String[] args) {
    	System.out.println(new MyLambdaFunction() {
			public int max(int a, int b) {
				return a > b ? a : b;
			}
		}.max(3, 5));
    }
}

위 함수를 람다와 함수형 인터페이스를 이용해 리팩토링해보자.

@FunctionalInterface
interface MyLambdaFunction {
	int max(int a, int b);
}

public class Lambda {
	public static void main(String[] args) {
    	MyLambdaFunction mlf = (int a, int b) -> a > b ? a : b ;
        mlf.max(2, 10);
    }
}

구현

  • 인터페이스 내부에 1개의 abstract 함수 선언 (하나만 가능)
  • @FunctionalInterface 어노테이션 붙이기

선언

  • 람다식으로 생성된 순수 함수는 함수형 인터페이스로만 선언 가능
  • 다른 방법으로는 이름을 정의할 수 없음

다음 글에서는 Stream API 연산에 대해 자세히 다룰 것.

자세한 내용 참고

profile
성장 중독 | 서버, 데이터, 정보 보안을 공부합니다.

0개의 댓글