일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 쓰기지연sql저장소 쿼리실행순서
- plugin local
- 로컬에서 플러그인 추가
- intellij 플러그인 만들기
- 쿼리실행순서
- Oracle
- group by group by rollup 차이
- sql 테스트 사이트
- 포트앤어댑터 아키텍처
- JPA
- IntelliJ
- 쓰기지연저장소
- Java
- Stream
- 스트림
- intellij 플러그인 개발
- Flush
- ls -lgaf
- error 2002 (hy000): can't connect to local mysql server through socket '/tmp/mysql.sock' (2)
- java 로 intellij 플러그인
- 중복컬럼dto매핑
- 자바
- 컬럼명중복
- 플러그인 로컬 테스트
- hibernate 쿼리실행 순서
- Kafka
- port&adapter architecture
- dto매핑우선순위
- 오라클쿼리테스트사이트
- 쿼리테스트사이트
- Today
- Total
개린이 탈출기
[Java] stream 의 peek 과 map의 차이 본문
그동안 자바에서 코드를 짤 때, 컬렉션을 순회하면서 어떠한 작업을 하고 싶을 땐, for문을 돌리거나 스트림의 map/filter 만을 이용했다.
그러다가 누군가가 peek 이라는 메서드를 사용한 것을 보았는데, 내가 평소에 map으로 처리했던 작업을 peek으로 처리하는 것 같아 보여 peek 에 대해 알아보았다.
우선 peek 영단어의 뜻은 '(재빨리) 훔쳐보다' 라는 뜻이다.
자바에서 peek은 다음과 같이 구현되어있다
@Override
public final Stream<P_OUT> peek(Consumer<? super P_OUT> action) {
Objects.requireNonNull(action);
return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
0) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
@Override
public void accept(P_OUT u) {
action.accept(u);
downstream.accept(u);
}
};
}
};
}
map 은 다음과 같이 구현되어 있다.
@Override
@SuppressWarnings("unchecked")
public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.apply(u));
}
};
}
};
}
코드를 읽어보았을 때, 가장 눈에 띄는 차이점은 두 메서드가 받는 파라미터와 반환타입이 다르다는 점이었다.
1. 우선 파라미터 타입을 비교해보면, Consumer 타입은 void형 인터페이스이고 Function 은 파라미터를 반환값이 있는 인터페이스이다.
2. 반환타입을 살펴보았을 때, peek의 반환타입은 Stream<P_OUT>으로 현재 스트림의 데이터 타입이 그대로 유지됨을 알 수 있다.
반면에 map의 반환타입은 Stream<R> 이므로 현재 스트림의 데이터 타입이 변할 수도 있음을 알 수 있다.
3. 가장 내부의 accept 함수를 보면 peek 은 P_OUT 을 그대로 받아 넘기므로 결과적으로 스트림에 변화가 없고
반면에 map 은 mapper.apply(u) 를 통해 새로운 데이터타입을 전달받아 변환하므로 스트림에 변화가 생긴다.
...
그렇지만 map을 사용한다고 해서 항상 스트림 내부에서 사용하는 객체가 생성되는 것은 아니다. map 을 사용했다 하더라도 스트림 내에서 기존 객체를 그대로 반환하거나 필드만 수정하는 경우, 같은 객체가 그대로 전달되는 경우도 있다.
그래서 나름의 결론을 짓자면,
데이터 타입이 변환되어야 할 때는 map을 사용하고, 타입 변화가 필요 없는 경우에는 peek을 사용하면 될 것 같다!다만, map을 사용해도 타입 변화가 없는 경우에는 둘의 차이가 크지 않을 것 같다.
map 이 조금 더 광범위하게 사용되는 느낌인걸까?
'에러 해결 목록' 카테고리의 다른 글
[JAVA] Gradle 구동 과정 간단 정리 (2) | 2024.11.05 |
---|---|
[JAVA] List 에 add가 왜 안돼? (feat.stream) (0) | 2024.11.04 |
[JPA] flush 와 clear 의 차이 (5) | 2024.09.26 |
[Oracle] (+) 유무에 따른 WHERE 절의 조건 해석 (1) | 2024.09.10 |
modify run configuration 실행 옵션 수정 (2) | 2024.07.29 |