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
- java map
- java 자료구조 활용
- 격파르타비전공자
- sqld자격증합격
- java map 출력
- 노베이스부트캠프
- javaJRE
- 항해99후기
- java알고리즘문제풀이
- 인터프린터언어
- 컴파일
- 프로그래머스
- java list 저장
- 프로그래머스제일작은수
- 코딩부트캠프후기
- java참조자료형
- javaJVM
- java기본자료형
- java list 출력
- java set 출력
- 격파르타후기
- 격파르타합격후기
- java알고리즘
- 작은수제거하기
- java set 저장
- java최솟값구하기
- 비전공자sqld
- 격파르타장점
- 항해15기
- java map 저장
Archives
- Today
- Total
코딩과 결혼합니다
230821 - 코드 리팩토링! 57줄이나 줄었어용 ^^ 본문
728x90
어마무시한 기존 코드
package com.gavoza.backend.domain.tag.service;
import com.gavoza.backend.domain.post.dto.LocationResponseDto;
import com.gavoza.backend.domain.post.dto.PostInfoResponseDto;
import com.gavoza.backend.domain.post.dto.PostResultDto;
import com.gavoza.backend.domain.post.entity.Post;
import com.gavoza.backend.domain.post.repository.PostRepository;
import com.gavoza.backend.domain.post.response.PostListResponse;
import com.gavoza.backend.domain.tag.dto.hashtagPostResponseDto;
import com.gavoza.backend.domain.user.dto.UserResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class TagService {
private final PostRepository postRepository;
//인기 순위 태그 조회(전체)
public List<String> allRankNumber(String gu, String dong) {
Map<String, Integer> idFrequencyMap = new HashMap<>();
List<String> hashTagResponseDtos = new ArrayList<>();
List<Post> postList = postRepository.findAllByGuAndDong(gu,dong);
for (Post post : postList) {
if (Objects.isNull(post.getHashtag())) {
continue;
}
String hashTag = post.getHashtag();
String[] hashTagList = hashTag.split("#");
for (String tagName : hashTagList) {
if (tagName == "") {
continue;
}
idFrequencyMap.put(tagName, idFrequencyMap.getOrDefault(tagName, 0) + 1);
}
}
//엔트리의 값을 내림차순으로 비교합니다. entry2의 값이 entry1의 값보다 크면 양수를 반환하고, 반대의 경우 음수를 반환하며 같으면 0을 반환합니다.
//따라서, 이 정렬을 통해 언급 횟수가 큰 엔트리가 리스트의 앞쪽으로 오게 됩니다.
List<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(idFrequencyMap.entrySet());
sortedEntries.sort((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()));
List<String> rankedIds = new ArrayList<>();
for (Map.Entry<String, Integer> entry : sortedEntries) {
rankedIds.add(entry.getKey());
}
for (int i = 0; i < rankedIds.size(); i++) {
if (i >= 6) {
break;
}
hashTagResponseDtos.add(rankedIds.get(i));
}
return hashTagResponseDtos;
}
//카테고리별 인기 순위 태그 조회
public List<String> categoryRankNumer(String category, String gu, String dong) {
Map<String, Integer> idFrequencyMap = new HashMap<>();
List<String> hashTagResponseDtos = new ArrayList<>();
List<Post> postList = postRepository.findAllBycategoryAndGuAndDong(category, gu, dong);
for (Post post : postList) {
if (Objects.isNull(post.getHashtag())) {
continue;
}
String hashTag = post.getHashtag();
String[] hashTagList = hashTag.split("#");
for (String tagName : hashTagList) {
if (tagName == "") {
continue;
}
idFrequencyMap.put(tagName, idFrequencyMap.getOrDefault(tagName, 0) + 1);
}
}
List<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(idFrequencyMap.entrySet());
sortedEntries.sort((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()));
List<String> rankedIds = new ArrayList<>();
for (Map.Entry<String, Integer> entry : sortedEntries) {
rankedIds.add(entry.getKey());
}
for (int i = 0; i < rankedIds.size(); i++) {
if (i >= 6) {
break;
}
hashTagResponseDtos.add(rankedIds.get(i));
}
return hashTagResponseDtos;
}
//인기 순위 태그별 post 조회(전체)
public PostListResponse hashtagPostResponseDtos(int size, int page, String hashtagName,String type, String gu, String dong) {
Pageable pageable = PageRequest.of(page,size, Sort.by(Sort.Direction.DESC, "createdAt"));
List<hashtagPostResponseDto> hashtagPostResponseDtos = new ArrayList<>();
List<PostResultDto> postResultDtos = new ArrayList<>();
Page<Post> postPage = type.equals("popular")
?postRepository.findAllByHashtagContainingAndGuAndDongOrderByPostViewCountDesc(hashtagName,pageable,gu, dong)
:postRepository.findAllByHashtagContainingAndGuAndDongOrderByCreatedAtDesc(hashtagName,pageable, gu, dong);
if (postPage == null) {
throw new IllegalArgumentException("존재하지 않는 태그입니다.");
}
for (Post checkHashTagName : postPage) {
String[] checkHashTagNames = checkHashTagName.getHashtag().split("#");
UserResponseDto userResponseDto = new UserResponseDto(checkHashTagName.getUser());
PostInfoResponseDto postInfoResponseDto = new PostInfoResponseDto(checkHashTagName);
LocationResponseDto locationResponseDto = new LocationResponseDto(checkHashTagName.getGu(),checkHashTagName.getDong(),checkHashTagName.getLat(),checkHashTagName.getLng());
postResultDtos.add(new PostResultDto(userResponseDto, postInfoResponseDto,locationResponseDto));
//이제 확인해
for (int i = 0; i < checkHashTagNames.length; i++) {
if (hashtagName.equals(checkHashTagNames[i])) {
hashtagPostResponseDtos.add(new hashtagPostResponseDto(checkHashTagName, hashtagName));
break;
}
}
}
return new PostListResponse("검색 조회 성공", postPage.getTotalPages(), postPage.getTotalElements(), size , postResultDtos);
}
//카테고리별 인기 순위 태그 post 조회
public PostListResponse categoryHashtagPostResponseDtos(int size, int page, String hashtagName, String category, String type, String gu, String dong) {
// 페이지 및 사이즈 계산
Pageable pageable = PageRequest.of(page,size, Sort.by(Sort.Direction.DESC, "createdAt"));
List<hashtagPostResponseDto> hashtagPostResponseDtos = new ArrayList<>();
List<PostResultDto> postResultDtos = new ArrayList<>();
Page<Post> postPage = type.equals("popular")
? postRepository.findAllByCategoryAndHashtagContainingAndGuAndDongOrderByPostViewCountDesc(category,hashtagName,pageable,gu, dong)
: postRepository.findAllByCategoryAndHashtagContainingAndGuAndDongOrderByCreatedAtDesc(category,hashtagName, pageable, gu, dong);
if (postPage == null) {
throw new IllegalArgumentException("존재하지 않는 태그 혹은 존재하지 않는 카테고리 입니다.");
}
for (Post checkhashtagName : postPage) {
String[] checkhashTagNames = checkhashtagName.getHashtag().split("#");
UserResponseDto userResponseDto = new UserResponseDto(checkhashtagName.getUser());
PostInfoResponseDto postInfoResponseDto = new PostInfoResponseDto(checkhashtagName);
LocationResponseDto locationResponseDto = new LocationResponseDto(checkhashtagName.getGu(),checkhashtagName.getDong(),checkhashtagName.getLat(),checkhashtagName.getLng());
postResultDtos.add(new PostResultDto(userResponseDto, postInfoResponseDto,locationResponseDto));
for (int i = 0; i < checkhashTagNames.length; i++) {
if (hashtagName.equals(checkhashTagNames[i])) {
hashtagPostResponseDtos.add(new hashtagPostResponseDto(checkhashtagName, hashtagName));
break;
}
}
}
return new PostListResponse("검색 조회 성공", postPage.getTotalPages(), postPage.getTotalElements(), size , postResultDtos);
}
}
기존의 코드이다. 굉장히 뭔지 읽히지도 않고 중복되는 코드들도 너무 많다. 특히 포스트에서 해시태그를 추출해내는 부분!
아래의 이부분이 계속 반복되므로 메서드를 따로 빼주었다.
기존 코드에서 반복되는 부분
List<Post> postList = postRepository.findAllByGuAndDong(gu,dong);
for (Post post : postList) {
if (Objects.isNull(post.getHashtag())) {
continue;
}
String hashTag = post.getHashtag();
String[] hashTagList = hashTag.split("#");
for (String tagName : hashTagList) {
if (tagName == "") {
continue;
}
idFrequencyMap.put(tagName, idFrequencyMap.getOrDefault(tagName, 0) + 1);
}
}
//엔트리의 값을 내림차순으로 비교합니다. entry2의 값이 entry1의 값보다 크면 양수를 반환하고, 반대의 경우 음수를 반환하며 같으면 0을 반환합니다.
//따라서, 이 정렬을 통해 언급 횟수가 큰 엔트리가 리스트의 앞쪽으로 오게 됩니다.
List<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(idFrequencyMap.entrySet());
sortedEntries.sort((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()));
List<String> rankedIds = new ArrayList<>();
for (Map.Entry<String, Integer> entry : sortedEntries) {
rankedIds.add(entry.getKey());
}
for (int i = 0; i < rankedIds.size(); i++) {
if (i >= 6) {
break;
}
hashTagResponseDtos.add(rankedIds.get(i));
}
return hashTagResponseDtos;
}
getHashTagsFromPosts 라는 이름으로 공통되는 코드를 뽑아 낸다음 for문으로 6개의 태그만 뽑아내는 부분을 더욱 단순화 시켰다.
return rankedIds.subList(0, Math.min(rankedIds.size(), 6)) 이런 식으로!
중복되는 코드를 메서드로 만들어줌
//포스트에서 해시태그를 추출
private List<String> getHashTagsFromPosts(List<Post> postList) {
Map<String, Integer> idFrequencyMap = new HashMap<>();
for (Post post : postList) {
if (Objects.isNull(post.getHashtag())) {
continue;
}
String hashTag = post.getHashtag();
String[] hashTagList = hashTag.split("#");
for (String tagName : hashTagList) {
if (!tagName.isEmpty()) {
idFrequencyMap.put(tagName, idFrequencyMap.getOrDefault(tagName, 0) + 1);
}
}
}
List<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(idFrequencyMap.entrySet());
sortedEntries.sort((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()));
List<String> rankedIds = new ArrayList<>();
for (Map.Entry<String, Integer> entry : sortedEntries) {
rankedIds.add(entry.getKey());
}
return rankedIds;
}
다음으로는 반환하는 Dto를 다른걸로 쓰게 되면서 더이상 쓰지도 않고 저 과정을 대체 왜 거치는지 모를 로직
->이거 List<hashtagPostResponseDto> hashtagPostResponseDtos = new ArrayList<>();
...
for (Post checkHashTagName : postPage) {
->이거 String[] checkHashTagNames = checkHashTagName.getHashtag().split("#");
UserResponseDto userResponseDto = new UserResponseDto(checkHashTagName.getUser());
PostInfoResponseDto postInfoResponseDto = new PostInfoResponseDto(checkHashTagName);
LocationResponseDto locationResponseDto = new LocationResponseDto(checkHashTagName.getGu(),checkHashTagName.getDong(),checkHashTagName.getLat(),checkHashTagName.getLng());
postResultDtos.add(new PostResultDto(userResponseDto, postInfoResponseDto,locationResponseDto));
//이제 확인해
->이거 for (int i = 0; i < checkHashTagNames.length; i++) {
if (hashtagName.equals(checkHashTagNames[i])) {
hashtagPostResponseDtos.add(new hashtagPostResponseDto(checkHashTagName, hashtagName));
break;
}
}
}
인기순위 태그 뽑아내는 것도 아니고 이미 내가 찾고 싶은 태그가 포함된 post들이 잘 나오고 있는데 굳이 #을 기준으로 스플릿을 하고 같은 해시태그가 있는지 확인한다???? 이럴수가.. 굉장히 비효율적인 코드를 그대로 가지고 있었다. 심지어 쓰지도 않고 있었다. 그대로 지웠다.
코드 리팩토링 후
package com.gavoza.backend.domain.tag.service;
import com.gavoza.backend.domain.post.dto.LocationResponseDto;
import com.gavoza.backend.domain.post.dto.PostInfoResponseDto;
import com.gavoza.backend.domain.post.dto.PostResultDto;
import com.gavoza.backend.domain.post.entity.Post;
import com.gavoza.backend.domain.post.repository.PostRepository;
import com.gavoza.backend.domain.post.response.PostListResponse;
import com.gavoza.backend.domain.user.dto.UserResponseDto;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class TagService {
private final PostRepository postRepository;
//전체 - 인기 태그 순위
public List<String> allRankNumber(String gu, String dong) {
List<Post> postList = postRepository.findAllByGuAndDong(gu, dong);
List<String> rankedIds = getHashTagsFromPosts(postList);
return rankedIds.subList(0, Math.min(rankedIds.size(), 6));
}
//카테고리 - 인기 태그 순위
public List<String> categoryRankNumer(String category, String gu, String dong) {
List<Post> postList = postRepository.findAllBycategoryAndGuAndDong(category, gu, dong);
List<String> rankedIds = getHashTagsFromPosts(postList);
//6위까지만 가져오기
return rankedIds.subList(0, Math.min(rankedIds.size(), 6));
}
//전체 - 태그별 post
public PostListResponse hashtagPostResponseDtos(int size, int page, String hashtagName, String type, String gu, String dong) {
Pageable pageable = PageRequest.of(page, size);
//정렬
Page<Post> postPage = type.equals("popular")
? postRepository.findAllByHashtagContainingAndGuAndDongOrderByPostViewCountDesc(hashtagName, pageable, gu, dong)
: postRepository.findAllByHashtagContainingAndGuAndDongOrderByCreatedAtDesc(hashtagName, pageable, gu, dong);
if (postPage == null) {
throw new IllegalArgumentException("존재하지 않는 태그입니다.");
}
List<PostResultDto> postResultDtos = new ArrayList<>();
for (Post postList : postPage) {
UserResponseDto userResponseDto = new UserResponseDto(postList.getUser());
PostInfoResponseDto postInfoResponseDto = new PostInfoResponseDto(postList);
LocationResponseDto locationResponseDto = new LocationResponseDto(postList.getGu(), postList.getDong(), postList.getLat(), postList.getLng());
postResultDtos.add(new PostResultDto(userResponseDto, postInfoResponseDto, locationResponseDto));
}
return new PostListResponse("검색 조회 성공", postPage.getTotalPages(), postPage.getTotalElements(), size, postResultDtos);
}
//카테고리 - 태그별 post
public PostListResponse categoryHashtagPostResponseDtos(int size, int page, String hashtagName, String category, String type, String gu, String dong) {
Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));
Page<Post> postPage = type.equals("popular")
? postRepository.findAllByCategoryAndHashtagContainingAndGuAndDongOrderByPostViewCountDesc(category, hashtagName, pageable, gu, dong)
: postRepository.findAllByCategoryAndHashtagContainingAndGuAndDongOrderByCreatedAtDesc(category, hashtagName, pageable, gu, dong);
if (postPage == null) {
throw new IllegalArgumentException("존재하지 않는 태그 혹은 존재하지 않는 카테고리 입니다.");
}
List<PostResultDto> postResultDtos = new ArrayList<>();
for (Post checkHashtagName : postPage) {
UserResponseDto userResponseDto = new UserResponseDto(checkHashtagName.getUser());
PostInfoResponseDto postInfoResponseDto = new PostInfoResponseDto(checkHashtagName);
LocationResponseDto locationResponseDto = new LocationResponseDto(checkHashtagName.getGu(), checkHashtagName.getDong(), checkHashtagName.getLat(), checkHashtagName.getLng());
postResultDtos.add(new PostResultDto(userResponseDto, postInfoResponseDto, locationResponseDto));
}
return new PostListResponse("검색 조회 성공", postPage.getTotalPages(), postPage.getTotalElements(), size, postResultDtos);
}
//포스트에서 해시태그를 추출
private List<String> getHashTagsFromPosts(List<Post> postList) {
Map<String, Integer> idFrequencyMap = new HashMap<>();
for (Post post : postList) {
if (Objects.isNull(post.getHashtag())) {
continue;
}
String hashTag = post.getHashtag();
String[] hashTagList = hashTag.split("#");
for (String tagName : hashTagList) {
if (!tagName.isEmpty()) {
idFrequencyMap.put(tagName, idFrequencyMap.getOrDefault(tagName, 0) + 1);
}
}
}
List<Map.Entry<String, Integer>> sortedEntries = new ArrayList<>(idFrequencyMap.entrySet());
sortedEntries.sort((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()));
List<String> rankedIds = new ArrayList<>();
for (Map.Entry<String, Integer> entry : sortedEntries) {
rankedIds.add(entry.getKey());
}
return rankedIds;
}
}
일단 가독성이 굉장히 좋아졌다. 내가 써놓고도 이게 뭐였더라 한참을 생각했어야 했는데 말이다. 물론 이보다 더 좋은 코드가 있을 수 있지만 일단 이정도로 만족! 좋은 코드들을 많이 접해봐야겠다.
'코딩과 매일매일♥ > Seoulvival' 카테고리의 다른 글
230826 - 댓글 + 대댓글 좋아요 기능 구현 (1) | 2023.08.26 |
---|---|
230824 - 인기 순위 태그 조회하기 (0) | 2023.08.25 |
230818 - [ERD 설계]기획과 데이터를 다루는 것을 빡세게 생각 하고 정하는 것의 중요성 (0) | 2023.08.19 |
230817 - 기상청 날씨 API 받아오기 (0) | 2023.08.17 |
230815 - 코드 리팩토링 멋진 3중 for문을 하나의 for문으로 (2) | 2023.08.15 |