• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    해결됨

스트림 질문 있습니다.

23.07.16 16:34 작성 23.07.16 17:10 수정 조회수 477

1

구글링 해봤는데 명확하게 이해가 되지 않아서 질문 남깁니다.

222.PNG

ㅁㅁㅁ.PNG

기존의 코드에서 메서드 참조, 여기서는 생성자 참조를 사용하는 코드로 변경해보려고 했는데 안 되더라구요.

map(아이디, 이름, 나이) 부분에 어쨌든 user.getId() 이런 식으로 해야 하는데 user 참조변수를 가져올 방법도 없고.. 이런 경우에는 메서드 참조를 사용하면 안 되는 건가요??

users.stream().map(UserResponse::new(User::getId, User::getName, User::getAge)) -> 이것도 안되네요

 

names 리스트를 메서드 참조 사용할 때는 names의 지네릭 타입이 String이니까 별도의 변수를 생성할 필요 없이 생성자 참조로 사용할 수 있는 것인지 궁금합니다.

결론은 메서드 참조가 명확하게 이해가 안되네요..

답변 1

답변을 작성해보세요.

0

안녕하세요, hope님! 질문 주셔서 감사합니다! 😊

 

제가 질문을 정확하게 이해하지는 못해서 (죄송합니다 ㅠㅠㅠ) 하나씩 말씀드려보겠습니다!

List<User> users = userRepository.findAll();
users.stream().map(user -> new UserResponse(user.getId(), ... ))
  .collect(Collectors.toList());

와 같은 코드를 메소드 레퍼런스로 바꾸고 싶다고 말씀해주셨어요!

 

자 이때 핵심은 map 이라는 함수에 method reference를 적용하는 것이겠죠?!

그렇다면 map 함수가 어떤 타입의 매개변수를 받는지 확인해보아야 합니다!

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

map 을 클릭해 들어가 보시면 다음과 같이 Function 타입의 매개변수를 받고 있네요! 이 Function 타입을 다시 한 번 확인해보면

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
}

와 같이 생긴 함수형 인터페이스를 확인할 수 있게 되죠!! 👍

 

자 그렇다면, 여기서 한 가지 결론을 알 수 있습니다. map(객체::함수) 에서 메소드 레퍼런스를 사용하려면, 그 함수의 형태가 R apply(T t) 여야 한다. 즉, 하나의 매개변수를 받고 하나의 결과를 반환하는 함수여야만 우리는 map 을 사용할 수 있는 것이죠!

(여기가 핵심이에요!!! 이걸 이해하셔야 메소드 레퍼런스를 이해하실 수 있습니다! 혹시 여기가 어려우시다면 함수형 인터페이스라는 키워드로 조금 더 검색해보셔도 좋을 것 같아요!! 😊)

 

그런데, 지금 UserResponse(Long id, String name, Integer age) 생성자 같은 경우는 하나의 매개변수를 받는게 아니라 3개의 매개 변수를 받고 있네요! 울가 map 함수를 쓰려면 함수 형태가 R apply(T t) - 하나의 매개변수를 받음 여야 하는데 말이죠!

때문에 이 생성자는 method reference로 활용할 수 없습니다.

 

그럼 다른 방법은 있을까요?! 넵! 생성자가 매개변수를 하나만 받도록 바꾸면 되죠! 예를 들어, UserResponse(User u) 는 User 타입 매개변수 하나만 받으니 method reference로 사용할 수 있을겁니다!

이를 활용하면 코드는 다음과 같이 변할거에요!

List<User> users = userRepository.findAll();
users.stream().map(UserResponse::new)
  .collect(Collectors.toList());

// UserResponse 클래스 안에 추가된 생성자
public UserResponse(User u) {
  this.id = u.getId();
  this.name = u.getName();
  this.age = u.getAge();
}

 

답변이 도움이 되었으면 좋겠습니다 ㅎㅎㅎㅎ

어려운 부분은 더 편하게 여쭤봐주세요!! 감사합니다! 🙏

아 추가로 List<String>은 왜 에러가 나지 않는가도 위의 내용과 동일합니다!

UserResponse::new를 할 때

public UserResponse(String name) {

}

이라는 매개변수가 하나 있는 생성자가 있기에, 에러가 나지 않는거에요!!

감사합니다! 🙏

hope님의 프로필

hope

질문자

2023.07.17

한 번에 이해 됐습니다!

정성스러운 답변 감사힙니다~!

아이고~ 다행입니다 ㅎㅎㅎ

또 궁금한 점 생기시면 편하게 질문 남겨주세요!! 🙏