Knowledge/Java

[Java] Stream 중간연산 map에 대하여

발달중인 망고 2023. 11. 1. 14:11

map은 Stream API의 중간 연산 중 하나로, 스트림의 각 요소를 특정 방식으로 변환하는 역할을 합니다. 주어진 함수를 각 요소에 적용하여, 그 결과로 구성된 새로운 스트림을 반환합니다.

map의 기본 형태:

<R> Stream<R> map(Function<? super T, ? extends R> mapper)
  • T: 원본 스트림의 요소 유형
  • R: 변환된 스트림의 요소 유형
  • mapper: 각 요소에 적용될 함수

map 사용 예제:

정수 리스트의 각 요소를 제곱하기:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squaredNumbers = numbers.stream()
    .map(n -> n * n)
    .collect(Collectors.toList());

문자열 리스트에서 각 문자열의 길이 얻기:

List<String> words = Arrays.asList("apple", "banana", "cherry");
List<Integer> wordLengths = words.stream()
    .map(String::length)
    .collect(Collectors.toList());

객체 리스트에서 특정 속성 값만 추출하기

class User {
    private String name;
    private int age;

    // ...

    public String getName() {
        return name;
    }
}

List<User> users = Arrays.asList(new User("Seongho", 25), new User("Zzang", 5));
List<String> names = users.stream()
    .map(User::getName)
    .collect(Collectors.toList());

map과 관련된 주요 특징 및 사항:

타입 변환: map 연산은 스트림의 요소 유형을 변환할 수 있습니다. 예를 들어, Stream<String>을 Stream<Integer>로 변환하는 것이 가능합니다.

List<String> stringList = List.of("1", "2", "3", "4", "5");

List<Integer> intList = stringList.stream()
        .map(Integer::parseInt)
        .collect(Collectors.toList());

 

Optional과의 연계: map은 Optional 클래스에도 존재하며, 값이 존재할 경우 주어진 함수를 값에 적용하여 Optional을 반환합니다.

Optional<String> optional = Optional.of("123");
Optional<Integer> result = optional.map(Integer::parseInt);

 

다른 중간 연산과의 연계: map은 다른 중간 연산과 연계하여 사용될 수 있습니다. 예를 들어, filter를 사용하여 특정 조건을 만족하는 요소만을 걸러낸 후 map으로 해당 요소들을 변환할 수 있습니다.

    private List<String> findWinnerNames(RacingCars cars) {
        return cars.getAllCars().stream()
                .filter(car -> winnerDistance == car.getCurrentPosition())
                .map(Car::getName)
                .collect(Collectors.toList());
    }

cars.getAllCars 라는 List<Car>에서 .filter를 통해 if (winnerDistance == car.getCurrentPosition())과 같은 연산을 이뤄냅니다. filter 조건에 만족하는 Car는 getName메소드의 return값으로 치환되어 List<String> 형태로 반환됩니다.

주의사항:

  • map만 사용하고 최종 연산을 수행하지 않으면 아무런 동작도 발생하지 않습니다. 스트림은 지연 평가 모델을 따르기 때문에 중간 연산만 수행하고 최종 연산을 호출하지 않으면 중간 연산도 실제로 실행되지 않습니다.
  • map은 상태를 변화시키지 않는 순수 함수를 사용하는 것이 좋습니다. map 내에서 상태나 외부 변수를 변경하는 부작용이 있는 연산을 수행하면 예기치 않은 결과나 병렬 스트림 처리에서 문제가 발생할 수 있습니다.