본문 바로가기
Programming/Java

자바 Map관련 알고리즘 문제 리팩토링 과정 기록

by hyunipad 2023. 12. 1.
반응형

정말 오랜만에 글을 쓴다.

이제부턴 조금 편하게 글을 써 내려가도록 마음을 먹었다.

그리고 말투도 편하게 독백체로... 독백체가 좀 더 감정이 잘 실리고 글도 술술 잘 적힌다.

 

오늘 포스팅은 백준 알고리즘 10816번을 풀다가 초기 코드에서 리팩토링을 해간 과정이 재밌어서 기록해 둔다.

먼저 백준 알고리즘 10816번에 대해

단계별로 풀어가고 있는데 현재는 집합과 Map 단계인데 이 문제가 실버 4 수준인지는 잘 모르겠다.

Map이라는 자료구조가 들어가서 그런가...

 

문제 자체는 굉장히 직관적이게 숫자 카드의 개수를 Map에다가 저장하면 된다.

아래는 초기 코드

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashMap;

public class Main {

	public static void main(String[] args) throws IOException {
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		
		int N = Integer.parseInt(br.readLine());
		HashMap<Integer, Integer> cardCount = new HashMap<>();
		String[] cards = br.readLine().split(" ");
		for(int i = 0 ; i < N ; i++) {
			int card = Integer.parseInt(cards[i]);
			if(cardCount.containsKey(card)) {
				cardCount.put(card, cardCount.get(card) + 1);
			}else {
				cardCount.put(card, 1);
			}
		}
		
		int M = Integer.parseInt(br.readLine());
		String[] check = br.readLine().split(" ");
		
		for(int i = 0 ; i < M ; i++) {
			int num = Integer.parseInt(check[i]);
			if(cardCount.containsKey(num)) {
				bw.write(String.valueOf(cardCount.get(num)) + " ");
			}else {
				bw.write(String.valueOf(0) + " ");
			}
			
		}
		
		br.close();
		bw.flush();
		bw.close();
	}
}

 

정답을 맞혔지만 코드가 상당히 마음에 안 들었다.

첫 번째로는 cardCount에 개수를 저장하는 방식 

두 번째로는 cardCount에서 개수를 꺼내는 방식(카드가 존재하지 않을 때 0을 따로 작성해야 하는 점이 상당히 거슬렸음)

 

처음에는 StringBuilder와 getOrDefault() 메서드를 사용하여 리팩토링 진행

StringBuilder result = new StringBuilder();

for(int i = 0 ; i < M ; i++) {

int num = Integer.parseInt(check[i]);

result.append(cardCount.getOrDefault(num, 0)).append(" ");

}

 

bw.write(result.toString());

br.close();

bw.flush();

bw.close();

 

두 번째로는 merge를 사용하여 키 값이 존재할 경우 기존의 value값과 새 value를 합친다.

for(int i = 0 ; i < N ; i++) {

int card = Integer.parseInt(cards[i]);

cardCount.merge(card, 1, (oldValue, newValue) -> oldValue + newValue);

}

 

나는 람다식으로 작성했지만 메서드 참조를 사용하여 아래와 같이 더 리팩토링이 가능하다.

메서드 참조는 익숙하지가 않아서 사용하지 않음.

for(int i = 0 ; i < N ; i++) {

int card = Integer.parseInt(cards[i]);

cardCount.merge(card, 1, Integer::sum);

}

 

최종코드

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashMap;

public class Number_10816 {

	public static void main(String[] args) throws IOException {
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
		
		int N = Integer.parseInt(br.readLine());
		HashMap<Integer, Integer> cardCount = new HashMap<>();
		String[] cards = br.readLine().split(" ");
		for(int i = 0 ; i < N ; i++) {
			int card = Integer.parseInt(cards[i]);
			cardCount.merge(card, 1, (oldValue, newValue) -> oldValue + newValue);
		}
		
//		for(int i = 0 ; i < N ; i++) {
//			int card = Integer.parseInt(cards[i]);
//			cardCount.merge(card, 1, Integer::sum);
//		}
		
		int M = Integer.parseInt(br.readLine());
		String[] check = br.readLine().split(" ");
		
		StringBuilder result = new StringBuilder();
		for(int i = 0 ; i < M ; i++) {
			int num = Integer.parseInt(check[i]);
			result.append(cardCount.getOrDefault(num, 0)).append(" ");
		}
		
		bw.write(result.toString());
		br.close();
		bw.flush();
		bw.close();
	}
}

아래에서부터 시작인데, 확실히 리팩토링이 진행되닌깐 메모리랑 시간이 향상됨 재밌다.

 

이후로는 혼자 놀다가 재밌었던 부분을 글로 계속 작성할 거 같다.

아니면 서적리뷰나...

반응형

댓글