ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] #6 람다(Lambda), 스트림(Stream)
    Software engineer/Java 2023. 5. 2. 16:24

    람다(Lambda)

    Java 8에서 추가된 람다(lambda)는 익명 함수(anonymous function)를 정의하는 방법입니다. 한마디로 함수의 표현 형식입니다. 람다를 사용하면 코드를 간결하게 작성하고, 코드의 가독성과 유지보수성을 높일 수 있습니다. 람다는 다음과 같은 문법으로 정의됩니다.

    // return이 없는 경우
    (parameters) -> expression
    (parameters) -> { statements; }
    
    // return문의 경우 중괄호(Braces)와 함께 생략 가능
    // (parameters) -> { return result; }
    (parameters) -> result;

    위 문법에서, parameters는 메서드의 매개변수를 나타내며, expression 또는 statements는 람다의 실행 코드를 나타냅니다.

    또한 ::(Double Colon Operator)를 통해 더 간결하게 표현도 가능하다.

    [인스턴스]::[메소드명(or new)]
    
    // 람다 표현식 () -> {} 에서만 사용 가능.
    // static 메소드인 경우 인스턴스 대신 클래스 이름으로 사용할 수도 있다.
    
    Arrays.stream(new int[]{1,2,3,4,5}).forEach(System.out::println);

     

     

    람다는 다양한 상황에서 사용될 수 있습니다. 다음은 람다를 사용하여 컬렉션을 처리하는 예제입니다.

    public class LambdaExample {
        public static void main(String[] args) {
            List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    
            // forEach() 메서드와 람다 표현식을 사용하여 각 요소 출력
            numbers.forEach(number -> System.out.println(number));
    
            // filter() 메서드와 람다 표현식을 사용하여 짝수만 필터링
            List<Integer> evenNumbers = numbers.stream()
                                                .filter(number -> number % 2 == 0)
                                                .collect(Collectors.toList());
    
            // map() 메서드와 람다 표현식을 사용하여 각 요소를 제곱한 값으로 변환
            List<Integer> squaredNumbers = numbers.stream()
                                                    .map(number -> number * number)
                                                    .collect(Collectors.toList());
    
            // reduce() 메서드와 람다 표현식을 사용하여 모든 요소를 더한 값 계산
            int sum = numbers.stream().reduce(0, (x, y) -> x + y);
        }
    }

    위 예제에서는 람다 표현식을 사용하여 컬렉션을 처리하는 다양한 방법을 보여주고 있습니다.

    첫 번째 예제에서는 forEach() 메서드와 람다 표현식을 사용하여 각 요소를 출력하고 있습니다.

    두 번째 예제에서는 filter() 메서드와 람다 표현식을 사용하여 짝수만 필터링하고 있습니다. 이를 통해 컬렉션의 요소를 조건에 따라 필터링할 수 있습니다.

    세 번째 예제에서는 map() 메서드와 람다 표현식을 사용하여 각 요소를 제곱한 값을 반환하고 있습니다. 이를 통해 컬렉션의 요소를 변환할 수 있습니다.

    네 번째 예제에서는 reduce() 메서드와 람다 표현식을 사용하여 모든 요소를 더한 값을 반환하고 있습니다. 이를 통해 컬렉션의 요소를 집계할 수 있습니다.

     

    람다는 함수형 인터페이스와 함께 사용되어 함수형 프로그래밍의 기능을 활용할 수 있습니다. 람다를 사용하면 코드를 간결하게 작성할 수 있으며, 자바 8에서 추가된 스트림(Stream) API와 함께 사용하면 컬렉션을 효과적으로 처리할 수 있습니다.

     

     

    스트림(Stream)

    Java 8에서 추가된 Stream은 컬렉션(Collection)과 배열(Array) 같은 자료구조의 요소를 하나씩 차례로 처리할 수 있는 기능입니다. Stream을 이용하면 요소들을 더 쉽게 처리할 수 있고, 불필요한 연산을 줄여서 코드의 가독성과 성능을 향상할 수 있습니다.

    이런 Stream은 중간 연산(Intermediate Operations)과 최종 연산(Terminal Operations)으로 구분됩니다.

    중간 연산(Intermediate Operations)

    • 중간 연산은 스트림에서 요소를 추출하여 필터링하거나 가공하는 등의 작업을 수행합니다. 이는 스트림의 데이터를 변환하고 가공하는 역할을 합니다.
    • 대표적인 Intermediate Operations로는 filter(), map(), distinct(), sorted(), limit(), skip() 등이 있습니다.

    최종 연산(Terminal Operations)

    • 최종 연산은 가공된 결과를 반환하는 작업을 수행합니다. 이는 스트림의 처리 결과를 반환하거나 출력하는 역할을 합니다.
    • 대표적인 Terminal Operations로는 forEach(), toArray(), reduce(), collect() 등이 있습니다.

    Intermediate Operations는 하나 이상의 Intermediate Operations로 구성될 수 있습니다. 이러한 Intermediate Operations는 연속적으로 적용될 수 있습니다. 즉, 파이프라인을 구성할 수 있습니다. 이를 통해 불필요한 작업을 최소화하고, 성능을 최적화할 수 있습니다.

    하지만, Terminal Operations가 호출되기 전까지는 Intermediate Operations가 실제로 수행되지 않습니다. 이러한 지연(Lazy) 연산을 통해, 스트림의 처리 속도와 메모리 사용량을 최적화할 수 있습니다. 이를 설명하기 위한 예제 입니다.

    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
    Stream<Integer> stream = numbers.stream()
            // 중간 연산
            .filter(n -> n % 2 == 0)
            // 중간 연산
            .map(n -> {
                System.out.println("mapping " + n);
                return n * 2;
            });
    
    System.out.println("Stream created");
    // 최종 연산
    stream.forEach(System.out::println);

    위 예제는 1부터 5까지의 숫자를 담은 리스트에서 짝수를 필터링하고, 각각의 값을 2배로 만들어 스트림을 생성합니다. 이때, map() 메소드에서 각각의 값을 2배로 만들 때마다 "mapping n"이라는 문자열을 출력합니다. 그리고, 생성된 스트림에서 각각의 요소를 출력합니다. 실행 결과는 다음과 같습니다.

    Stream created
    mapping 2
    2
    mapping 4
    4

    Terminal Operations가 호출되면, Intermediate Operations가 순차적으로 수행됩니다. 이때, 중간 연산은 스트림의 요소를 변환하고 가공하며, 최종 연산은 가공된 결과를 반환합니다. 이를 통해 스트림의 데이터를 효율적으로 처리할 수 있습니다.

     

Designed by Tistory.