코딩테스트 준비

[Java] 파일 정리

graph-dev 2023. 6. 19. 14:11
728x90

파일 정리

문제 살펴보기

파일 정리 백준 문제

문제 요약

파일을 확장자 별로 정리해서 개수를 정리합니다. 이것을 확장자 기준 사전 순으로 오름차순 정렬하여 출력합니다.

확장자는 . 을 사용하므로 그걸 쪼개서 이름과 개수(빈도)를 알파벳 순서대로 출력하면 되는 문제입니다.

 

전략

  1. 기존에 잘 알려진 HashMap을 사용해볼 수 있습니다. 다만 알파벳 순서대로 차후에 sort 작업을 수행해야 합니다.
  2. 새롭게 등장한 TreeMap 을 사용해본다. 자동으로 알파벳 순서대로 정렬해주므로 편리합니다.

 

공통 사항

  1. Java로 백준에 제출할 때에는 Main 으로 클래스 이름을 지정해야 합니다.
  2. 입력은 Scanner 객체 sc로 받습니다.
  3. 숫자와 문자가 동시에 입력받아야 한다면, 두가지 전략이 있습니다.
    1. 숫자는 sc.nextInt() 로 받고, sc.nextLine() 으로 줄바꿈을 입력받고 그 다음에 문자열인 sc.nextLine을 입력받아야 정상적으로 숫자와 문자열이 입력됩니다.
    2. 숫자든 문자열이든 모조리 sc.nextLine() 으로 입력받고, 차후에 숫자형으로 변환(parseInt, Integer.valueOf)을 수행하여 활용합니다.

HashMap

  1. 숫자 입력받고, 해당 숫자의 길이만큼 파일명을 담아줄 문자열 객체를 생성하고, 확장자명과 개수를 입력받을 Map 객체 생성하기.
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
				// 구분을 위한 줄바꿈 처리
        sc.nextLine();

        String[] fileArr = new String[N];
        Map<String, Integer> fileMap = new HashMap<>();

 

 

2. 문자열도 입력받아서 위에서 만든 fileArr 배열에 입력하고, map에 입력할 때 mapKey를 생성해서 파일명에서 . 을 기준으로 분할합니다.

...
        for(int i = 0; i < fileArr.length; i++){
            fileArr[i] = sc.nextLine();
...
        }

 

3. 이를 containsKey 메서드를 통해 기존의 키값에 포함한다면 해당 키에 value 값만 1씩 증가시킵니다. 빈도수는 value가 되니 이걸 재귀적으로 입력해야 안전하게 map에 입력이 됩니다.

 

for(int i = 0; i < fileArr.length; i++){
            fileArr[i] = sc.nextLine();
            String mapKey = fileArr[i].split("[.]")[1];
            if(fileMap.containsKey(mapKey)){
                fileMap.put(mapKey, fileMap.get(mapKey) + 1);
            } else {
                fileMap.put(mapKey, 1);
            }
        }

결과는 아래와 같습니다.

8
sbrus.txt
spc.spc
acm.icpc
korea.icpc
sample.txt
hello.world
sogang.spc
example.txt

이 map에 담긴 값을 출력해서 살펴보면 다음과 같습니다.

{txt=3, world=1, spc=2, icpc=2}

이 값을 보면 txt부터 랜덤하게 출력됩니다. 이 순서를 교정하기 위해 Collections.sort() 를 사용해보겠습니다.

컬렉션 형태 중에서 List<String>을 사용해서 구현해봤습니다.

keySet이라는 리스트를 만들고, 그 안에 생성할 때부터 key 값의 집합인 keySet()

메서드로 맵에 있는 키값만 모아둔것을 파라미터로 전달합니다.

 

Collections.sort() : 컬렉션 내 요소를 오름차순으로 정렬해줍니다.

List<String> keySet = new ArrayList<>(fileMap.keySet());

        // 키 값으로 오름차순 정렬
        Collections.sort(keySet);

        for(String key : keySet){
            System.out.println(key + " " + fileMap.get(key));
        }

출력하면 다음과 같습니다.

icpc 2
spc 2
txt 3
world 1

내림차순은, Collections.sort(리스트, Collections.reverseOrder()) 사용합니다.

// 키 값으로 오름차순 정렬
        Collections.sort(keySet, Collections.reverseOrder());
        System.out.println(keySet);
        for(String key : keySet){

            System.out.println(key + " " + fileMap.get(key));
        }

 

출력하면, 다음과 같습니다.

world 1
txt 3
spc 2
icpc 2

 

이번에는 배열 객체를 통해 정렬합니다.

Object[] keyArr = fileMap.keySet().toArray();
        Arrays.sort(keyArr);

//        이 경우 정렬된 것이 배열로 만들어 졌으니 그대로 이걸 사용해서 for문으로 출력함.
        for(int i = 0; i < keyArr.length; i++){
            System.out.println(keyArr[i] + " " + fileMap.get(keyArr[i]));
        }

위 방법은 List 객체 대신에 toArray() 메서드를 통해 배열 객체를 만드는 것입니다.

배열 객체를 Object 타입으로 만들고, 그리고 Arrays.sort() 메서드로 정렬한 다음 for 문으로 바로 그 배열을 출력하면 됩니다.

 

TreeMap

트리맵의 가장 큰 특징이, 입력된 키를 자동으로 오름차순으로 정렬해준다는 점입니다.

코드 살펴보기

처음에 TreeMap() 으로 선언합니다. 나머지 과정은 HashMap과 동일하게 수행하되, 별도의 정렬 작업 없이 바로 출력합니다.

Map<String, Integer> fileMap = new TreeMap<String, Integer>();

        for(int i = 0; i < fileArr.length; i++){
            fileArr[i] = sc.nextLine();
            String mapKey = fileArr[i].split("[.]")[1];
            if(fileMap.containsKey(mapKey)){
                fileMap.put(mapKey, fileMap.get(mapKey) + 1);
            } else {
                fileMap.put(mapKey, 1);
            }
        }

        // 향상된 for문을 활용해서 출력.
        for(String key : fileMap.keySet()){

            // 문자열을 연결한다.
            System.out.println(key + " " + fileMap.get(key));
        }

출력하면 위와 동일하게 나타납니다. 간단하죠?

world 1
txt 3
spc 2
icpc 2