본문 바로가기
Baekjoon/브론즈 1

[백준][JAVA/자바] 9506번: 약수들의 합 - stream 사용해 해결하는 방법

by 감자감자곰 2024. 1. 5.

<단계>

브론즈 1


<문제>

 

9506번: 약수들의 합

어떤 숫자 n이 자신을 제외한 모든 약수들의 합과 같으면, 그 수를 완전수라고 한다. 예를 들어 6은 6 = 1 + 2 + 3 으로 완전수이다. n이 완전수인지 아닌지 판단해주는 프로그램을 작성하라.

www.acmicpc.net


<코드>

import java.util.*;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        while (true) {
            int n = scanner.nextInt(); //n
            if (n == -1) {
                break;
            }
            ArrayList<Integer> divisors = new ArrayList<>();

            for (int i = 1; i < n; i++) {
                if (n % i == 0) { //약수인 경우
                    divisors.add(i);
                }
            }

            int divSum = 0;

            for (int j : divisors) {
                divSum += j;
            }

            if (divSum == n) {
                //출력 방법1
                System.out.print(n + " = ");
                divisors.stream().sorted().limit(1).forEach(System.out::print);
                for (int i = 1; i < divisors.size(); i++) {
                    System.out.print(" + ");
                    divisors.stream().sorted().skip(i).limit(1).forEach(System.out::print);
                }
                System.out.println();

//                //출력 방법2
//                String joinedDivisors = divisors.stream()
//                        .sorted()
//                        .map(Object::toString)
//                        .collect(Collectors.joining(" + "));
//
//                System.out.println(n + " = " + joinedDivisors);
            } else {
                System.out.println(n + " is NOT perfect.");
            }
        }

    }
}

<트러블 슈팅>

 

ArrayList인 divisors에 담겨있는 요소들을 정렬하고, "+"와 함께 하나씩 출력해야 하기 위해 stream()을 최대한 활용해보려고 했는데, 원하는 대로 출력시키기는 부분에서 조금 고민을 했다.


//출력 방법1
System.out.print(n + " = ");
divisors.stream().sorted().limit(1).forEach(System.out::print);
for (int i = 1; i < divisors.size(); i++) {
    System.out.print(" + ");
    divisors.stream().sorted().skip(i).limit(1).forEach(System.out::print);
}
System.out.println();

이런 식으로 정렬된 ArrayList에서 첫 원소를 출력하고, " + "와 원소들을 짝으로 만들어 출력시키는 방법을 첫번째로 사용했다.


//출력 방법2
String joinedDivisors = divisors.stream()
        .sorted()
        .map(Object::toString)
        .collect(Collectors.joining(" + "));

System.out.println(n + " = " + joinedDivisors);

그리고, 두번째 방법으로 다음과 같은 방법을 사용했다. 구글링을 통해 알아낸 방법이라, 새로 알게 된 내용을 정리해보고자 한다.

 

.map(Object::toString)

.map()은 stream의 중간 연산 중 하나이다. stream의 각 요소에 대해 toString을 호출해 문자열로 변환하기 위해 .map(Object::toString)이라고 작성해 주었다.

 

collect( ) 메서드

stream의 최종 연산 중 하나이며, stream의 요소들을 다양한 형태로 변환할 수 있는 기능을 제공한다.

  • 리스트로 변환: stream.collect(Collectors.toList())은 스트림의 모든 요소를 리스트로 변환함
  • 문자열 결합: stream.collect(Collectors.joining())은 스트림의 문자열 요소를 하나의 문자열로 결합함
  • 그룹화: stream.collect(Collectors.groupingBy())는 주어진 기준에 따라 요소를 그룹화하여 맵으로 반환함
  • 요약 연산: stream.collect(Collectors.summarizingInt())와 같은 메소드는 요소의 통계적 요약(예: 합계, 평균 등)을 제공함

이 외에도 여러 작업이 가능하다.

 

Collectors.joining( )

java.util.stream.Collectors 클래스에 포함된 정적 메서드로서, 문자열 stream의 요소를 하나의 문자열로 결합하는 데 사용된다.

여기에서도 여러 작업이 가능하다.

  • joining(): 단순히 stream의 모든 문자열 요소를 연결함
  • joining(CharSequence delimiter): 타입 인자(구분자)를 받아서, stream의 각 요소 사이에 이 구분자를 삽입함
  • joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix): 세 개의 인자(구분자, 접두사, 접미사)를 받아서, 스트림의 요소들 사이에 구분자를 넣고, 결과 문자열의 시작과 끝에 각각 접두사와 접미사를 추가함

댓글