중복 데이터를 제거하기 위해 Stream distinct를 사용합니다.
동일한 객체의 판단하는 기준은 Object.equals(Object)의 결과 값이다. String 객체의 경우 equals()가 이미 구현되어 있습니다.
- Stream<T>.distinct() : Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.
List<String> strings = Arrays.asList("hello", "world", "hello", "java", "hello");
strings.stream().distinct().forEach(System.out::println); // "hello", "world", "java"
만약 String객체가 아닌 VO를 사용한다면, equals, hashCode가 재정의 되어야 합니다.
- Object.equals(Objecr) : Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
List<StringVO> stringVOList = Arrays.asList(new StringVO("hello"), new StringVO("world"), new StringVO("hello"), new StringVO("java"), new StringVO("hello"));
stringVOList.stream().distinct().forEach(stringVO -> System.out.println(stringVO.getStr()));
public class StringVO {
public String str;
public StringVO(String str) {
this.str = str;
}
public void setStr(String str) {
this.str = str;
}
public String getStr() {
return str;
}
@Override
public boolean equals(Object o) {
if (o instanceof StringVO) {
return this.str.equals(((StringVO) o).getStr()); // 값 비교
}
return false;
}
@Override
public int hashCode() {
return str.hashCode();
}
}
Lombok을 사용한다면, @EqualsAndHashCode 어노테이션을 사용하여 재정의할 수 있습니다.
equals, hashCode를 재정의하지 않고 사용하는 방법은 다음과 같습니다.
/**
* Stream에서 distinct 다중키 비교를 위함 (hashCode, equals 재정의를 하지 않고)
* - 예) list.stream().filter(distinctByKeys(UserVO::getName, UserVO::getAge)).distinct()...
*
* @param keyExtractors Object[]
* @return Predicate
*/
public static <T> Predicate<T> distinctByKeys(Function<? super T, ?>... keyExtractors) {
final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();
return t -> {
final List<?> keys = Arrays.stream(keyExtractors).map(ke -> ke.apply(t)).collect(Collectors.toList());
return seen.putIfAbsent(keys, Boolean.TRUE) == null;
};
}
List<StringVO> stringVOList = Arrays.asList(new StringVO("hello"), new StringVO("world"), new StringVO("hello"), new StringVO("java"), new StringVO("hello"));
stringVOList.stream().filter(distinctByKeys(StringVO::getStr)).distinct().forEach(stringVO -> System.out.println(stringVO.getStr()));
[Reference]
https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/stream/Stream.html
https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/Object.html
'java' 카테고리의 다른 글
[java] Enum Hierarchy(계층 구조) getChildren, getParent (0) | 2021.02.02 |
---|---|
[java] 쿠키 생성, 삭제와 browser's cookie max size (0) | 2021.01.08 |
[java] StringBuffer getChars (Chars to String) (0) | 2020.10.31 |
[java] 임시 비밀번호 생성 (Random vs SecureRandom vs RandomStringUtils) (7) | 2020.10.31 |
[java] 예외처리 Exception handling (0) | 2020.10.11 |
댓글