반응형
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
- RestTemplate
- ClientHttpRequestInterceptor
- 개방/폐쇄 원칙
- AOP
- 쓰레드 안전
- auto configuration
- fotmatter
- LogInterceptor
- JsonType
- 포맷터
- findAny
- Spring Boot
- AOP target
- java
- JsonStringType
- vaultTemplate
- gradle
- spring
- ResponseBodyAdvice
- AOP this
- AOP 매개변수
- @AutoConfiguration
- Save Action
- Thread Safety
- Stream
- Starter
- jpa
- findFirst
- AccessLevel
- restTemple
Archives
- Today
- Total
맨땅에 헤딩하는 개바른자
[Java] Stream > distinct 본문
반응형
git
https://github.com/ymwoo88/stream/tree/feature/distinct-%EC%98%88%EC%A0%9C
설명
distinct는 stream 데이터 중에서 중복이 제거된 stream을 반환해주는 기능을 제공합니다.
distinct
이 스트림의 개별 요소(Object.equals(Object)에 따름)로 구성된 스트림을 반환합니다.
정렬된 스트림의 경우 개별 요소의 선택이 안정적입니다(중복된 요소의 경우 만나는 순서에서 처음 나타나는 요소가 보존됨). 정렬되지 않은 스트림의 경우 안정성이 보장되지 않습니다.
이것은 상태 저장 중간 작업입니다.
보고:
새로운 스트림
API 참고:
병렬 파이프라인에서 distinct()에 대한 안정성을 유지하는 것은 상대적으로 비용이 많이 들고(작업이 상당한 버퍼링 오버헤드가 있는 전체 장벽으로 작동해야 함) 안정성이 종종 필요하지 않습니다. 정렬되지 않은 스트림 소스(예: generate(Supplier))를 사용하거나 unordered()로 정렬 제약 조건을 제거하면 상황의 의미 체계가 허용하는 경우 병렬 파이프라인에서 distinct()를 훨씬 더 효율적으로 실행할 수 있습니다. 발생 순서와의 일관성이 필요하고 병렬 파이프라인에서 distinct()를 사용하여 성능 또는 메모리 사용률이 저하되는 경우 sequence()를 사용하여 순차적 실행으로 전환하면 성능이 향상될 수 있습니다.
Stream<T> distinct();
예제
- 샘플 데이터
@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) 단순 스트링의 중복제거
@Test
@DisplayName("유저목록에서 취미목록을 추출 후 중복제거")
void case1() {
List<User> examUserList = User.getExamUserList();
// 유저들의 취미를 뽑는다. (중복제거 X)
List<String> nonDistinctHobbies = examUserList
.stream()
.map(User::getHobbies)
.flatMap(Collection::stream)
.toList();
nonDistinctHobbies.forEach(s -> log.info("[nonDistinctHobbies] Hobbies info : {}", s));
// 유저들의 취미를 뽑고 중복제거 한다.
List<String> distinctHobbies = examUserList
.stream()
.map(User::getHobbies)
.flatMap(Collection::stream)
.distinct()
.sorted()
.toList();
distinctHobbies.forEach(s -> log.info("[distinctHobbies] Hobbies info : {}", s));
}
20:36:43.281 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [nonDistinctHobbies] Hobbies info : 골프
20:36:43.284 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [nonDistinctHobbies] Hobbies info : 영화감상
20:36:43.285 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [nonDistinctHobbies] Hobbies info : 등산
20:36:43.285 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [nonDistinctHobbies] Hobbies info : 캥핌
20:36:43.285 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [nonDistinctHobbies] Hobbies info : 골프
20:36:43.285 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [nonDistinctHobbies] Hobbies info : 낚시
20:36:43.286 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [distinctHobbies] Hobbies info : 골프
20:36:43.286 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [distinctHobbies] Hobbies info : 낚시
20:36:43.287 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [distinctHobbies] Hobbies info : 등산
20:36:43.287 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [distinctHobbies] Hobbies info : 영화감상
20:36:43.287 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- [distinctHobbies] Hobbies info : 캥핌
중복제거 전과 중복제거 후의 결과를 보면 "골프" 항목이 중복제거 된 것을 확인 할 수 있다.
예졔2) 객체 기준으로 중복제거
- 객체 기준으로 중복제거는 메모리의 주소 기준으로 중복제거가 된다.
@Test
@DisplayName("객체 기준으로 중복제거")
void case2() {
SendMail example = SendMail.valueOf("sender@ymwoo.com", "to@ymwoo.com");
List<SendMail> sendMailList = List.of(
example, // 동일주소의 객체를 중복으로 List에 추가
example, // 동일주소의 객체를 중복으로 List에 추가
SendMail.valueOf("sender@ymwoo.com", "to111@ymwoo.com"),
SendMail.valueOf("sender@ymwoo.com", "to222@ymwoo.com"), // 주소값은 다르나 같은 데이터를 List에 추가
SendMail.valueOf("sender@ymwoo.com", "to222@ymwoo.com") // 주소값은 다르나 같은 데이터를 List에 추가
);
List<SendMail> distinctSendMail = sendMailList
.stream()
.distinct()
.toList();
// 결과
distinctSendMail.forEach(sendMail -> {
log.info("sendMail : {}", sendMail);
});
}
20:45:16.523 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- sendMail : SendMail(sender=sender@ymwoo.com, to=to@ymwoo.com)
20:45:16.528 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- sendMail : SendMail(sender=sender@ymwoo.com, to=to111@ymwoo.com)
20:45:16.528 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- sendMail : SendMail(sender=sender@ymwoo.com, to=to222@ymwoo.com)
20:45:16.528 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- sendMail : SendMail(sender=sender@ymwoo.com, to=to222@ymwoo.com)
주소 값이 같은 객체는 중복제거되어 1개만 로그에 찍혔고, 주소값은 다르나 같은 데이터는 중복제거되지 않은 결과를 알 수 있다.
예졔3) 객체 특정조건 기준으로 중복제거
객체 내에 Object.equals(Object o) 기능을 구현해줘야한다.
isWorking 기준으로 중복제거하는 코드를 작성하였다.
샘플데이터에는 총 3개의 User정보가 있으며 2개가 중복되는 데이터가 존재 한다.
@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(); }
@Test
@DisplayName("객체 특정조건 기준으로 중복제거")
void case3() {
List<User> examUserList = User.getExamUserList()
.stream()
.sorted(Comparator.comparing(User::getAge))
.toList();
List<User> distinctUserList = examUserList
.stream()
.distinct()
.toList();
// 결과
distinctUserList.forEach(user -> {
log.info("user : {}", user);
});
}
20:45:45.578 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- user : User(id=1, name=amil, email=amil@ymwoo.com, age=28, isWorking=true, hobbies=[골프, 영화감상])
20:45:45.587 [Test worker] INFO com.ymwoo.stream.distinct.StreamDistinctTest -- user : User(id=3, name=cho, email=cho@ymwoo.com, age=33, isWorking=false, hobbies=[등산, 캥핌])
결과를보면 2개가 중복되는 것이 1개로 줄어들었다
2개 중 제일 먼저 확인된 데이터가 남고 그 뒤로 확인되는 중복 된 데이터가 제거 된다.
참조
반응형
'JAVA > Stream' 카테고리의 다른 글
[Java] Stream > reduce (0) | 2023.06.20 |
---|---|
[Java] Stream > foreach (0) | 2023.06.20 |
[Java] Stream > flatMap (0) | 2023.06.08 |
[Java] Stream > map (0) | 2023.06.08 |
[Java] Stream > sorted (0) | 2023.05.31 |