[JAVA] java Object List특정 값 중복제거

윤재열·2022년 7월 26일
0

Java

목록 보기
55/71
post-custom-banner

List에서 중복 제거를 하려면 기본적으로 Collections에는 stream API 사용시 distinct 라는 중복 제거 메서드가 있습니다.

  • Stream API 의 distinct 메서드에는 Object의 equals로 비교하므로 객체 자체가 같은지를 비교합니다.

따라서 리터럴 형태의 String을 인자로 갖는 List 등은 비교가 가능하지만 , Dto 형태의 모델은 비교가 안되며 Object 자체도 같은 주소값을 가지는 경우는 가능하지만 안의 속성을 비교하고자 할때는 비교가 어렵습니다. 이런 경우 사용할 수 있는 Utils 클래스 입니다.

  • 만약 학생 정보를 담는 클래스가 있다고 가정해봅니다.

DTO Class

@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentInfo{
	
    private Long studentNo;
    
    private String name;
    
    private int age;
}    

중복 제거가 필요한 List

 StudentInfo s1 = new StudentInfo(1L,"codeA",22);
    StudentInfo s2 = new StudentInfo(2L,"codeB",25);
    StudentInfo s3 = new StudentInfo(3L,"codeC",29);
    StudentInfo s4 = new StudentInfo(4L,"codeD",21);
    StudentInfo s5 = new StudentInfo(5L,"codeJ",27);
    StudentInfo s6 = new StudentInfo(6L,"codeJ",28);


    List<StudentInfo> list = List.of(s1,s2,s3,s4,s5,s6);
  • List 객체에는 6개의 StudentInfo 가 담겨 있고, 이 중 이름(String name)이 중복 되는 대상은 지우려고 합니다.
    (이런 상황일때 Stream().distinct()는 효과가 없습니다.)

중복제거 Util class

  • 아래 Util 클래스는 특정 Key를 기준으로 filter 처리를 해서 넘기는 방법입니다.(Deduplication 뜻은 데이터 중복제거 입니다.)
public class DeduplicationUtils{
	
   public static <T> List<T> deduplication(final List<T> list,Function<? super T,?>key){
   		return list.stream.filter(deduplication(key))
			   .collect(Collectors.toList());
	}               
    
   private static <?> Predicate<T>(Function<? super T,?>key){
   	 final Set<Object>set = ConcurrentHashMap.newKeySet();
     return predicate -> set.add(key.apply(predicate));
   }     
  • Java 8의 Predicate는 Type T인자를 받고 boolean을 리턴하는 함수형 인터페이스 입니다.
  • 위의 메서드는 중복이 있는 list,중복 제거의 기준이 될 key를 인자로 받아,중복을 제거한 후 return 합니다.
  • Key는 Function 함수형 인터페이스 객체인데, input과 output이 같아 사실상 값을 반환하는 래퍼런스 메서드를 입력해주면 됩니다.
  • ConCurrentHashMap은 key,value 에 null을 허용하지 않습니다.
  • <? super T>
    • 상속관계에 존재하는 클래스만 자료형으로 받고 싶은 경우
    • T : 자식클래스로 고정으로 지정해주고 자식클래스와 연관이 있는 부모 클래스는 전부 적용이 됩니다.

테스트

public class DeDuplicationUtilTest {
    public static void main(String[] args) {

        StudentInfo s1 = new StudentInfo(1L, "codeA", 22);
        StudentInfo s2 = new StudentInfo(2L, "codeB", 25);
        StudentInfo s3 = new StudentInfo(3L, "codeC", 29);
        StudentInfo s4 = new StudentInfo(4L, "codeD", 21);
        StudentInfo s5 = new StudentInfo(5L, "codeJ", 27);
        StudentInfo s6 = new StudentInfo(6L, "codeJ", 28);


        List<StudentInfo> list = List.of(s1, s2, s3, s4, s5, s6);
        //이름이 같은 사람은 제거
        List<StudentInfo> deduplicationList = DeduplicationUtils.deduplication(list, StudentInfo::getName);

        deduplicationList.forEach(lists -> System.out.println(lists.toString()));

    }
}

  • 이렇게 해서 studentNo 가 6번인 ,이름이 codeJ, 나이가 28인 객체는 제외되어서 출력됩니다.
profile
블로그 이전합니다! https://jyyoun1022.tistory.com/
post-custom-banner

0개의 댓글