반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Stream
- ResponseBodyAdvice
- AccessLevel
- gradle
- findAny
- jpa
- ClientHttpRequestInterceptor
- Starter
- spring
- AOP this
- AOP
- fotmatter
- LogInterceptor
- @AutoConfiguration
- 포맷터
- findFirst
- 개방/폐쇄 원칙
- java
- auto configuration
- restTemple
- 쓰레드 안전
- vaultTemplate
- AOP 매개변수
- Spring Boot
- RestTemplate
- Thread Safety
- AOP target
- JsonStringType
- JsonType
- Save Action
Archives
- Today
- Total
맨땅에 헤딩하는 개바른자
[Java] Stream > toMap 본문
반응형
git
https://github.com/ymwoo88/stream/tree/feature/tomap-%EC%98%88%EC%A0%9C
설명
Stream 안의 데이터를 map의 형태로 반환해주는 collector 입니다.
KeyMapper는 데이터를 map의 key로 변환하는 Function을 의미합니다.
valueMapper는 데이터를 map의 value로 변환하는 Function을 의미합니다.
저같은 경우 다중 for문에서 if매핑 시 자주사용하는 방식인데
첫번째 for문을 toMap으로 키/값으로 선언한 후 두번째 for문을 돌리면서 map.get(key)로 매칭시키는 로직으로짜게되면
연산을 상당히 많이 줄일 수 있습니다.
collecor toMap
제공된 매핑 함수를 입력 요소에 적용한 결과 키와 값이 있는 Map에 요소를 누적하는 Collector를 반환합니다.
매핑된 키에 중복 항목이 포함된 경우(Object.equals(Object)에 따라) 수집 작업이 수행될 때 IllegalStateException이 발생합니다. 매핑된 키에 중복이 있을 수 있는 경우 toMap(Function, Function, BinaryOperator)를 대신 사용하십시오.
반환된 Map의 유형, 가변성, 직렬화 가능성 또는 스레드 안전성에 대한 보장은 없습니다.
매개변수:
keyMapper – 키를 생성하는 매핑 함수 valueMapper – 값을 생성하는 매핑 함수
보고:
키와 값이 입력 요소에 매핑 함수를 적용한 결과인 Map으로 요소를 수집하는 Collector
API 참고:
키 또는 값이 입력 요소가 되는 것이 일반적입니다. 이 경우 유틸리티 메서드 Function.identity()가 도움이 될 수 있습니다. 예를 들어, 다음은 학생을 평균 학점에 매핑하는 맵을 생성합니다.
Map<Student, Double> studentToGPA = Students.stream().collect(toMap(Function.identity(), student -> computeGPA(student)));
그리고 다음은 고유 식별자를 학생에게 매핑하는 지도를 생성합니다.
Map<String, Student> studentIdToStudent = Students.stream().collect(toMap(Student::getId, Function.identity()));
구현 참고 사항:
반환된 Collector는 동시적이지 않습니다. 병렬 스트림 파이프라인의 경우 결합기 기능은 한 맵의 키를 다른 맵으로 병합하여 작동하며 이는 비용이 많이 드는 작업일 수 있습니다. 결과가 순서대로 Map에 삽입될 필요가 없는 경우 toConcurrentMap(Function, Function)을 사용하면 더 나은 병렬 성능을 제공할 수 있습니다.
또한보십시오:
toMap(함수, 함수, BinaryOperator), toMap(함수, 함수, BinaryOperator, Supplier), toConcurrentMap(함수, 함수)
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return new CollectorImpl<>(HashMap::new,
uniqKeysMapAccumulator(keyMapper, valueMapper),
uniqKeysMapMerger(),
CH_ID);
}
예제
- 샘플 데이터
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private Long id;
private String name;
private String email;
private Integer age;
private Boolean isWorking;
private List<String> hobbies;
public static User getUserAmil() {
return User.builder()
.id(1L)
.name("amil")
.email("amil@ymwoo.com")
.age(28)
.isWorking(true)
.hobbies(List.of("골프", "영화감상"))
.build();
}
public static User getUserBenny() {
return User.builder()
.id(2L)
.name("benny")
.email("benny@ymwoo.com")
.age(26)
.isWorking(true)
.hobbies(List.of("골프", "낚시"))
.build();
}
public static User getUserCho() {
return User.builder()
.id(3L)
.name("cho")
.email("cho@ymwoo.com")
.age(33)
.isWorking(false)
.hobbies(List.of("등산", "캥핌"))
.build();
}
public static List<User> getExamUserList() {
return Arrays.asList(getUserAmil(), getUserCho(), getUserBenny());
}
@Override
public boolean equals(Object o) {
if (o instanceof User) {
return this.isWorking.equals(((User) o).getIsWorking()); // 값 비교
}
return false;
}
@Override
public int hashCode() {
return isWorking.hashCode();
}
}
- 예졔1) Collectors toMap 상황별 사용해보기
@Test
@DisplayName("Collectors toMap 상황별 사용해보기")
void case3() {
// keyMapper는 값을 그대로 키로, valueMapper는 Number is x 값으로 저장
Map<Integer, String> numberMap1 = Stream.of(3, 5, -4, 2, 6)
.collect(Collectors.toMap(x -> x, x -> "Number is " + x));
log.info("numberMap1 : {}", numberMap1);
// x -> x 같이 간단한 경우 Function에서 identity 메서드로 이미 제공하고 있어서 이를 이용해도 됩니다.
Map<String, Integer> numberMap2 = Stream.of(3, 5, -4, 2, 6)
.collect(Collectors.toMap(x -> "Number is " + x, Function.identity()));
log.info("numberMap2 : {}", numberMap2);
// numberMap2 예제에서 reverse 버전으로 작성봄 (원리를 알아야 거꾸로도 하니까 그냥 해봄)
Map<Integer, String> numberMap2Reverse = Stream.of(3, 5, -4, 2, 6)
.collect(Collectors.toMap(Function.identity(), x -> "Number is " + x));
log.info("numberMap2Reverse : {}", numberMap2Reverse);
// 키는 userId로, value는 User 엔티티 자체를 사용
List<User> users = User.getExamUserList();
Map<Long, User> userIdToUserMap = users.stream()
.collect(Collectors.toMap(User::getId, Function.identity()));
log.info("userIdToUserMap : {}", userIdToUserMap);
}
20:33:05.707 [Test worker] INFO com.ymwoo.stream.collector.tomap.StreamToMapTest -- numberMap1 : {2=Number is 2, 3=Number is 3, -4=Number is -4, 5=Number is 5, 6=Number is 6}
20:33:05.710 [Test worker] INFO com.ymwoo.stream.collector.tomap.StreamToMapTest -- numberMap2 : {Number is 6=6, Number is 5=5, Number is 3=3, Number is -4=-4, Number is 2=2}
20:33:05.710 [Test worker] INFO com.ymwoo.stream.collector.tomap.StreamToMapTest -- numberMap2Reverse : {2=Number is 2, 3=Number is 3, -4=Number is -4, 5=Number is 5, 6=Number is 6}
20:33:05.711 [Test worker] INFO com.ymwoo.stream.collector.tomap.StreamToMapTest -- userIdToUserMap : {1=User(id=1, name=amil, email=amil@ymwoo.com, age=28, isWorking=true, hobbies=[골프, 영화감상]), 2=User(id=2, name=benny, email=benny@ymwoo.com, age=26, isWorking=true, hobbies=[골프, 낚시]), 3=User(id=3, name=cho, email=cho@ymwoo.com, age=33, isWorking=false, hobbies=[등산, 캥핌])}
참조
반응형
'JAVA > Stream' 카테고리의 다른 글
[Java] Stream > groupingBy (0) | 2023.07.04 |
---|---|
[Java] Stream > findAny, findFirst (0) | 2023.07.04 |
[Java] Stream > reduce (0) | 2023.06.20 |
[Java] Stream > foreach (0) | 2023.06.20 |
[Java] Stream > distinct (0) | 2023.06.08 |