람다 활용

정다운·2025년 5월 12일

고급자바

목록 보기
4/7

람다 표현식과 스트림 사용법 정리

1. 명령형 vs 선언적 프로그래밍

명령형 프로그래밍(Imperative Programming)

  • 어떻게(How) 해결할지를 단계별로 명시
  • 주로 for, while, if 등의 제어문을 사용하여 반복과 조건을 직접 제어
  • 상태 변화를 명확히 관리하고, 코드의 흐름이 직관적이지만 복잡한 로직에서 중복 코드 발생 가능

선언적 프로그래밍(Declarative Programming)

  • 무엇(What)을 수행할지를 명시하여 코드의 의도를 명확히 표현
  • 내부 구현은 숨기고 원하는 결과만을 나타냄으로써 코드의 간결성과 가독성을 높임
  • 필터링, 매핑, 집계 등의 연산을 표현할 때 특히 효과적임

2. 필터(Filter)와 맵(Map)

필터

  • 데이터 중 조건에 맞는 값만을 선별하는 작업
  • 주로 Predicate를 사용하며, boolean 값을 반환하는 함수형 인터페이스
Predicate<Integer> evenPredicate = n -> n % 2 == 0;
List<Integer> evenNumbers = numbers.stream()
                                   .filter(evenPredicate)
                                   .collect(Collectors.toList());

  • 데이터를 다른 값으로 변환하는 작업
  • 주로 Function을 사용하며, 입력값을 다른 타입이나 형태로 변환하는 역할 수행
Function<String, Integer> lengthMapper = s -> s.length();
List<Integer> lengths = strings.stream()
                               .map(lengthMapper)
                               .collect(Collectors.toList());

GenericFilter와 GenericMapper

  • 제네릭을 도입하여 다양한 데이터 타입에 대해 필터링과 매핑을 유연하게 적용 가능
  • 코드 중복을 최소화하고 유지보수성을 높임
List<Integer> filtered = GenericFilter.filter(numbers, n -> n % 2 == 0);
List<Integer> mapped = GenericMapper.map(filtered, n -> n * 2);

3. 스트림(Stream)

스트림 개념

  • 데이터를 흐름으로 보고 이를 연속적인 연산으로 처리할 수 있도록 지원하는 추상화된 개념
  • 메서드 체인을 사용하여 간결하게 코드를 작성 가능

스트림의 장점

  • 명확한 데이터 처리 흐름과 선언적인 코드로 가독성 향상
  • 내부 반복을 통해 개발자는 반복의 구현 방식이 아닌 데이터 처리의 의도에 집중 가능

스트림 예시

List<Integer> result = MyStream.of(numbers)
    .filter(n -> n % 2 == 0)
    .map(n -> n * 2)
    .toList();

4. 내부 반복 vs 외부 반복

외부 반복(External Iteration)

  • 개발자가 반복 제어 구조를 명시적으로 관리하며 데이터 순회
  • 반복문 내에서 조건에 따라 흐름 제어(break, continue)가 쉽지만, 반복 구조가 복잡해지면 코드의 가독성이 떨어질 수 있음
for (String s : list) {
    System.out.println(s);
}

내부 반복(Internal Iteration)

  • 반복 제어가 스트림 내부에서 관리됨
  • 개발자는 데이터 처리 방법(람다 표현식)에만 집중할 수 있음
  • 코드의 가독성 및 유지보수성이 뛰어나며 선언적 프로그래밍 방식과 어울림
list.stream().forEach(s -> System.out.println(s));

5. 정적 팩토리 메서드(Static Factory Method)

  • 객체 생성 방식을 메서드로 캡슐화하여 가독성을 높이고 생성자의 한계를 극복
  • 객체 생성 시 의미있는 이름을 부여하여 객체 생성 로직을 명확히 나타낼 수 있음
MyStream.of(numbers);
  • 간단한 생성 로직에는 일반 생성자가 적합하지만, 복잡하거나 명확한 이름이 필요한 경우 정적 팩토리 메서드가 유리함

정리

람다 표현식과 스트림을 적극 활용하면 선언적 프로그래밍을 통해 더욱 간결하고 직관적인 코드를 작성할 수 있다. 명령형 프로그래밍은 세부적인 제어가 필요할 때 적합하며, 상황에 따라 두 방식을 적절히 활용하면 더욱 효율적인 프로그래밍이 가능하다.

0개의 댓글