문제 링크 : https://programmers.co.kr/learn/courses/30/lessons/92334

 

코딩테스트 연습 - 신고 결과 받기

문제 설명 신입사원 무지는 게시판 불량 이용자를 신고하고 처리 결과를 메일로 발송하는 시스템을 개발하려 합니다. 무지가 개발하려는 시스템은 다음과 같습니다. 각 유저는 한 번에 한 명의

programmers.co.kr

 

문제 난이도 자체는 어렵지 않았으나, Map 을 사용하는 과정에서 Java 8 Stream 을 활용하기 전과 활용 후의 코드를 비교하고자 한다.

 

먼저, Java 8 Stream 을 활용하면 코드 가독성이 좋아지고, 코드량을 많이 줄일 수 있다는 장점이 있다.

 

아래는 문자열 리스트 중 특정 문자열로 시작하는 문자열 목록을 출력하는 예제 코드이다. 

 

(Java 8 Stream X)

        String[] id_list = {"muzi", "frodo", "apeach","neo"};
        String[] report = {"muzi frodo", "apeach frodo", "frodo neo", "muzi neo", "apeach muzi"};
        int k = 3;

        List<String> listNotStream = new ArrayList<>();
        for (String str : report) {
            if (str.startsWith("muzi ")) {
                listNotStream.add(str);
            }
        }
        System.out.println(listNotStream);

 

(Java 8 Stream O)

  • stream 을 사용한 후에는 map 혹은 filter 를 사용하면 for 선언문을 한것과 동일하다.
    • map 함수 내에는 반복문 내에서 element 별로 특정 코드를 실행할 수 있다.
    • filter 함수 내에는 반복문 내에서 if 문을 한개만 사용할 경우 유용하게 사용할 수 있다.
        String[] id_list = {"muzi", "frodo", "apeach","neo"};
        String[] report = {"muzi frodo", "apeach frodo", "frodo neo", "muzi neo", "apeach muzi"};
        int k = 3;

        List<String> listStream = Arrays.stream(report).filter(str -> str.startsWith("muzi ")).collect(Collectors.toList());
        System.out.println(listStream);

 

자 이제 Java Stream 을 사용하기 전 후 코드를 비교해보자.

(문제에 대한 설명은 위 링크에서 확인하시면 됩니다)

 

Stream 활용 전

  • id_list 에 있는 정보를 통해서, 인덱스 정보를 기억하기 위해서 map 을 사용하였으나 Stream 을 사용했다면 필요 없는 코드라고 생각된다.
  • 그리고 중복을 제거하기 위해서 reportMap 이라는 2차원 배열을 사용하였는데, 메모리 공간을 많이 사용할 수도 있다.
    public int[] solution(String[] id_list, String[] report, int k) {
        // int[] answer = {};
        int count = id_list.length;
        int[][] reportMap = new int[count][count];
        int[] reportCount = new int[count];
        int[] answer = new int[count];
        Map<String, Integer> map = new HashMap<>();
        for (int i = 0; i < id_list.length; i++)
            map.put(id_list[i],i);
        
        for (int i = 0; i < report.length; i++) {
            String[] rs = report[i].split(" ");
            
            int fromIndex = map.get(rs[0]);
            int toIndex = map.get(rs[1]);
            
            if (reportMap[fromIndex][toIndex] == 0) {
                reportMap[fromIndex][toIndex]+=1;
                reportCount[toIndex]+=1;
            }
        }
        
        for (int i = 0; i < reportCount.length; i++) {
            if (reportCount[i] >= k) {
                for (int j = 0; j < reportCount.length; j++) {
                    if (reportMap[j][i] > 0) {
                        answer[j]+=1;
                    }
                }
            }
        }
        return answer;
    }

 

Stream 활용 후

  • distinct 선언만으로도 for 선언문이 없어도 array 원소들의 중복을 제거한 리스트를 새로 만들 수 있다.
  • 위 코드와 다르게 2차원 배열을 사용하지 않았고, 메모리도 절약할 수 있다.
    public static int[] solution(String[] id_list, String[] report, int k) {

        List<String> list = Arrays.stream(report).distinct().collect(Collectors.toList());
        Map<String, Integer> count = new HashMap();
        for (String item : list) {
            String target = item.split(" ")[1];
            count.put(target, count.getOrDefault(target, 0) + 1);
        }

        return Arrays.stream(id_list).map(_user -> {
            String user = _user;
            List<String> reportList = list.stream().filter(str -> str.startsWith(user + " ")).collect(Collectors.toList());
            return reportList.stream().filter(s -> count.getOrDefault(s.split(" ")[1], 0) >= k).count();
        }).mapToInt(Long::intValue).toArray();
    }

 

그동안 Java 코딩을 할 때 Stream 을 잘 활용하지는 않았는데, 코드의 가독성도 좋고 효율적으로 코딩을 할 수 있어서 앞으로 많이 활용해야 겠다는 생각이 든다. 다음 문제부터는 Stream 을 최대한 활용해서 코드를 작성해 볼 예정입니다!

+ Recent posts