ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자료구조 효율성에 대한 고민
    내일배움캠프 2023. 3. 7. 22:26

     

    새벽까지 문제 해결 안되다 해결된 나의 모습

    딱 저 표정이였던것 같습니다. 어제 PartyPost 연관관계 때문에 삭제가 안되서 밤이라 머리가 잘 안돌아가는건지

    entity 에 아래 코드를 추가하고 와 이제 삭제되겠구나 큰 착각을 했었습니다 ㅠ..

    public void clearApplications() {
       this.applications.clear();
    }

     

    안되서 빙빙 돌아 뭐가 문제일까 보니까 해당 Repository 에 저장된 Application 을 삭제 한게 아니라서 인걸

    깨닫고 어제 리뷰한것 처럼 마무리 했습니다.

    오늘의 사진을 설명하느라 별걸 다 말하게 되네요

     

    ↓↓↓↓↓↓↓↓↓↓ NoShow 처리를 위한 자료 구조 고민 ↓↓↓↓↓↓↓↓↓↓

     

    처음 이중 배열로 처리하려 했다가 시행착오 끝에 아래로 방향을 바꿧습니다

    NoShow 와 User, PartyPost 연관관계를 맺고 User 객체에 NoShowCnt를 넣어서 처리하려고 했으나 제한사항이 많고PartyPost를 삭제하려 할 때 연관관계를 맺어줄 시 해당 NoShow들을 삭제해야 하기에 Id 값으로 받았고 DB에 저장했습니다.

    public NoShow(Long reporterId, Long reportedId, Long partyPostId) {
    		this.reporterId = reporterId;
    		this.reportedId = reportedId;
    		this.partyPostId = partyPostId;
    	}
    

     

     

    id 값만 받게 되니 어떻게 처리해야 되나 고민중에 ArrayList 각 배열에 reportedId 를 중복되는지 체크하고 넣고 uniqueRerpotedIds 에 넣어줬습니다

    List<Long> uniqueReportedIds = new ArrayList<>(joinUserSize);
    for (NoShow noShow : noShowList) {
        Long reportedId = noShow.getReportedId();
        if (!uniqueReportedIds.contains(reportedId)) {
            uniqueReportedIds.add(reportedId);
        }
    }
    

     

    다음 기능을 만들다가 굳이 contains 로 중복을 체크 하는게 아닌 처음부터 중복을 허용하지 않는 hashset 을 사용하여 단순화 하는게 좋겠다 생각해서 아래 처럼 로직을 수정했습니다.

    Set<Long> uniqueReportedIds = new HashSet<>();
    for (NoShow noShow : noShowList) {
        Long reportedId = noShow.getReportedId();
        uniqueReportedIds.add(reportedId);
    }
    

     

    끝으로 아래 로직을 추가하여 구현을 완료했는데

    for (Long reportedId : uniqueReportedIds) {
        int noShowCnt = 0;
        for (NoShow noShow : noShowList) {
            if (noShow.getReportedId().equals(reportedId)) {
                noShowCnt ++;
            }
        }
        if (noShowCnt >= Math.round(joinUserSize/2.0)) {
            User reported = findByUser(reportedId);
            reported.getProfile().plusNoShowCnt();
        }
    }
    

     

    reportedId 가 key 역활을 하고 있어서 Map 으로 바꿔도 좋겠다 판단했고 수정했습니다 똑같이 reportedId 를 key 값으로 주고 해당 값이 없으면 ArrayList 를 추가하고 noShow를 넣었습니다

    List<NoShow> noShowList = noShowRepository.findAllByPartyPostId(partyPost.getId());
    Map<Long, List<NoShow>> reportedNoShowMap = new HashMap<>();
    for (NoShow noShow : noShowList) {
        Long reportedId = noShow.getReportedId();
    		reportedNoShowMap.computeIfAbsent(reportedId, k -> new ArrayList<>()).add(noShow);
    }
    

     

    그 다음 Map.Entry 를 사용하여 key, value 를 가져와서 value 를 비교하고 cnt 를 올리며 마무리 지었습니다.

    for (Map.Entry<Long, List<NoShow>> entry : reportedNoShowMap.entrySet()) {
        Long reportedId = entry.getKey();
        List<NoShow> reportedNoShowList = entry.getValue();
        int noShowReportCnt = reportedNoShowList.size();
    
        if (noShowReportCnt >= Math.round(joinUserSize / 2.0)) {
            User reported = findByUser(reportedId);
            reported.getProfile().plusNoShowCnt();
        }
    }
    

     

    결과적으로 ArrayList, Hashset 을 사용할 때 보다 최소 한번의 목록에 대한 반복이 줄었네요.

     

    예상과 다른 결과가 있어 이어서 작성했습니다. ↓↓↓↓↓ 클릭 ↓↓↓↓↓

     

    ArrayList, HashSet, HashMap 성능 비교

    90 TIL 에 적었던 내용에 문제가 있어서 이어서 작성하겠습니다. 코드 상으로 보기에 목록을 한번 이상 덜 불러와 빠를 것이다 라고 착각을 했습니다. 문뜩 한번 실험해 봐야겠다 생각이 들었고

    holloweyed-snail.tistory.com

     

    아래는 전체 코드입니다.

    @Transactional
    public void checkingNoShow(List<PartyPost> posts) {
        for (PartyPost partyPost : posts) {
            partyPost.ChangeStatusEnd();
            int joinUserSize = partyPost.getApplications().size();
            List<NoShow> noShowList = noShowRepository.findAllByPartyPostId(partyPost.getId());
            Map<Long, List<NoShow>> reportedNoShowMap = new HashMap<>();
            for (NoShow noShow : noShowList) {
                Long reportedId = noShow.getReportedId();
                reportedNoShowMap.computeIfAbsent(reportedId, k -> new ArrayList<>()).add(noShow);
            }
            
            for (Map.Entry<Long, List<NoShow>> entry : reportedNoShowMap.entrySet()) {
                Long reportedId = entry.getKey();
                List<NoShow> reportedNoShowList = entry.getValue();
                int noShowReportCnt = reportedNoShowList.size();
    
                if (noShowReportCnt >= Math.round(joinUserSize / 2.0)) {
                    User reported = findByUser(reportedId);
                    reported.getProfile().plusNoShowCnt();
                }
            }
        }
    }
    

     

    '내일배움캠프' 카테고리의 다른 글

    국비교육 수료  (0) 2023.03.14
    88 TIL  (1) 2023.03.07
    87 TIL  (1) 2023.03.05
    86 TIL  (0) 2023.03.02
    85 TIL  (0) 2023.02.28
Designed by Tistory.