[Java] 배열과 ArrayList

Yunhye Park·2024년 1월 25일
0
post-thumbnail
post-custom-banner

(일반) 배열과 ArrayList

자바에서의 배열은 자바스크립트와 다르게 종류를 둘로 나눌 수 있다. 하나는 익히 알던 배열이고, 다른 하나는 동적으로 크기를 할당하는 ArrayList이다.

여기서 '동적'이라는 뜻은 자바가 강한 타입의 언어라는 데서 나온다. 배열을 생성할 때 타입은 물론 크기까지 지정해줘야 하는데 ArrayList는 크기를 동적으로, 즉 나중에 기입한다.

배열 예제

정수들의 평균값을 소수점 한 자리까지 나타내려면

1) printf 메서드로 %.1f 형식 지정자를 사용하거나
2) 암묵적/명시적 형변환을 해줘도 되겠다.

타입은 괜히 선언하는 게 아니고

package _03_array;

import java.util.Arrays;
import java.util.Scanner;

public class ArrayPrac {
    public static void main(String[] args) {
        System.out.println("5개의 정수를 입력하세요.");
        
        Scanner sc = new Scanner(System.in);
        
        int[] numArr = new int[5]; // 크기가 5인 배열 생성
        
        for(int i = 0; i<numArr.length; i++) {
            numArr[i] = sc.nextInt(); // 입력값 할당
            int result += numArr[i]; // <--- 문제 발생!
        }

    }
}

배열 생성 후, for 반복문으로 입력값을 해당 배열에 할당해줬다.

남은 건 입력값의 평균을 구하는 것인데, int result += numArr[i]로 해주려니 Unexpected token, Not a statement 등 증감연산자 이후 부분에서 에러가 났다.

왜 안 될까?

int로 타입을 명시한 건 좋은데 자바 컴파일러가 보기엔 result에 정수가 들어갔는지 아닌지 판별할 수가 없다. 초기값이 없으니까!

그래서 타입에 맞게 초기값 작성해주고, 정수에서 실수로 암묵적 형변환도 해준 코드가 바로 아래에 있다.

package _03_array;

import java.util.Arrays;
import java.util.Scanner;

public class ArrayPrac {
    public static void main(String[] args) {
        System.out.println("5개의 정수를 입력하세요.");
        Scanner sc = new Scanner(System.in);
        
        int[] numArr = new int[5]; // 크기가 5인 배열 생성
        
        int sum =  0; // 초기값 설정
        
        for(int i = 0; i<numArr.length; i++) {
            numArr[i] = sc.nextInt(); // 배열에 값 할당
            sum += numArr[i];
        }
        
        double sumD = sum; // 암묵적 형변환

         System.out.println("평균은 " + sumD/numArr.length);
    }
}

배열 메서드

배열 메서드 중 sort메서드를 작성하다가 문득 이런 생각이 들었다.

int[] unsortedArray = {56, 9, 32, 1, 7};

// 정렬
Arrays.sort(unsortedArray);

// 출력
System.out.println(Arrays.toString(unsortedArray));

정렬과 출력을 따로 하지 말고 한번에 하는 건 왜 안 되지?

sort 메서드는 반환값이 없는 void 타입이다. 그래서 toString 메서드 매개변수에 직접적으로 사용하면(Arrays.sort(unsortedArray)) void를 toString으로 바꾸려는 게 된다. 고로 컴파일 오류가 발생한다.

반환값 없는 fill 메서드도 마찬가지다.

copyOf, copyOfRange, toString은 반환값이 있기 때문에 단계를 나눌 필요 없이 한번에 출력까지 할 수 있다.
ex.

int[] oriArr = {1, 2, 3, 4, 5};

System.out.println(Arrays.toString(Arrays.copyOf(oriArr, 2)));

ArrayList 예제

문자열을 입력 받다가 'exit'을 입력하면 여태 입력한 문자열 보여주고 종료

Problem

1) sout을 반복문 내부에 넣지 않고, 바깥에 뒀다.
2) 기껏 내부에 넣었건만 break하는 조건을 잘못 설정했다.

Solution

어떤 조건문을 쓰든 상관 없었다. 중요한 건 각 조건문 특성에 맞게 설정을 해주는 건데 나는 이 점이 부족했다.

Ver1. while 문

package _03_array;

import java.util.ArrayList;
import java.util.Scanner;

public class ArrayListPrac {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        ArrayList<String> str = new ArrayList<>();

        while (true) {
            System.out.println("문자를 입력해 주세요.");
            String text = sc.nextLine();

            if (text.equals("exit")) {
                for (String val : str) {
                    System.out.println(val);
                }
                break;
            }
                        str.add(text);
        }
        sc.close();
    }
}

sout부터 ArrayList에 추가하는 것까지가 한 묶음으로 반복된다. 조건을 만족했을 때 while문을 빠져나갈 수 있도록 break를 알맞은 위치에 넣어주어야 한다.

Ver2. do while 문

        ...
        
        String input;
        do {
            System.out.println("문자를 입력해 주세요.");
            input = sc.nextLine();

            if(input.equals("exit")) {
                for (String val: str) {
                    System.out.println(val);
                }
            }
                    str.add(input);

        } while (!input.equals("exit"));
        
        ...

do while문은 사실상 두 개의 블록이 존재하기 때문에 statement가 아닌 바깥에서 변수를 선언(String input)해줘야 한다.

반복의 조건이 될 while 부분을 거꾸로 입력해서 문제였다. 문자 입력은 exit을 입력하지 않았을 때 발생하는 동작이므로, 부정 연산자를 달아주어야 한다.

profile
일단 해보는 편
post-custom-banner

0개의 댓글