Starbucks Caramel Frappuccino
본문 바로가기
  • 그래 그렇게 조금씩
JAVA/Java Start

8. 배열 Array

by Toughie 2024. 2. 2.

지금까지는 단순한 변수에 값을 할당하는 방식으로 데이터를 관리했었다.

하지만 여러 비슷한 변수들이 필요한 경우, 변수의 양이 굉장히 많은 경우 비효율적인 상황이 생길 수 있다.

public class Array1 {

    public static void main(String[] args) {
        int student1 = 90;
        int student2 = 80;
        int student3 = 70;
        int student4 = 60;
        int student5 = 50;
        //학생을 한 명 더 추가한다면
        int student6 = 40;
    
        //반복문으로 해결할 수 없나?
        for(int i=1; i <=6; i++) {
            System.out.println("학생" + i + "점수" + student1);
        }
        //변수명까지 i를 활용할 수는 없다..
        
        System.out.println("학생1 점수: "+ student1);
        System.out.println("학생2 점수: "+ student2);
        System.out.println("학생3 점수: "+ student3);
        System.out.println("학생4 점수: "+ student4);
        System.out.println("학생5 점수: "+ student5);

        System.out.println("학생6 점수: "+ student6);
    }
}

 

위와 같은 상황에서 배열을 활용하면 더욱 효율적인 코드를 작성할 수 있다.

배열은 같은 타입의 변수를 하나로 묶어둔 것이다.

(여러 타입의 변수를 담으려면 ArrayList를 사용해야 한다. Array는 전부 같은 타입의 요소만 담을 수 있다.)


기본형과 참조형

기본형(Primitive Type)

 

int, long, double, boolean처럼 변수에 사용할 값을 직접 넣는 데이터 타입.

기본형은 데이터의 사이즈가 명확하게 정해져 있다. (int는 4바이트, double은 8바이트)

 

참조형(Reference Type)

 

int[] students와 같이 데이터에 접근하기 위한 참조(주소)를 저장하는 데이터 타입 (객체, 클래스를 담는 변수)

 

배열은 왜 참조를 해야 할까?

기본타입은 선언과 동시에 사이즈가 정해지기 때문에 정적 할당이 이루어진다. (컴파일 타임)

(그렇기 때문에 더 빠르고 효율적인 메모리 사용이 가능하다.)

 

하지만 배열의 사이즈는 바뀔 수 있기 때문에 동적 메모리 할당의 가능성이 있다. (런 타임)

(ex. Scanner를 통해 배열의 사이즈를 프로세스에서 받는 경우)

즉 참조형을 활용하면 더 유연한 메모리 할당이 가능한 것이다. (new 키워드를 통한 객체 인스턴스 생성)


1차원 배열 초기화와 인덱싱

 public static void main(String[] args) {
        int[] students; //배열 주소를 담을 변수 선언
        students = new int[3];
//        students = new int[]; 배열의 사이즈를 누락한 경우 array dimension missing

        // 배열의 크기 만큼 메모리 공간을 확보(int의 경우 4byte * 3)
        // 배열 생성 후 배열의 참조값(주소)가 students 변수에 담긴다.
        // [I@3f99bd52  -- 정수 배열, 16진법 표기

        //3개의 int공간이 생성, 0으로 *자동 초기화
        //숫자는 0, boolean은 false, String은 null로 자동 초기화
		
        //배열의 사이즈를 벗어나는 경우_Swift에서의 index out of range
//        Index 5 out of bounds for length 5 at array.
		
        //인덱싱을 통한 배열 값 변경
        students[0] = 90;
        //[I@3f99bd52 참조값을 통해 실제 배열에 접근, 인덱스를 사용해서 해당 위치 요소에 접근 후 값 대입
        students[1] = 80;
        students[2] = 70;

        System.out.println("학생1 점수: "+ students[0]);
        System.out.println("학생2 점수: "+ students[1]);
        System.out.println("학생3 점수: "+ students[2]);

        System.out.println(students);
    }
 public static void main(String[] args) {

        int[] students = new int[5];
        int arraySize = students.length;
//        int[] students = new int[]{90, 80, 70, 60, 50}; //배열 생성과 초기화
//        int[] students = {90, 80, 70, 60, 50}; // 타입 추론 초기화
//        왜 중괄호를 쓰는 지 궁금했지만 그냥 java 문법인 것 같다.
        
        // 사이즈 5의 배열에 3개의 초기값을 주면 나머지는 0으로 자동 초기화 되나 싶었지만..
        // array creation with both dimension expression and initialization is illegal
//        int[] testArray = new int[5]{1,2,3};

        for (int i = 0; i < students.length; i++) {
            students[i] = 100 - (10 * (i + 1));
        }

        for (int i = 0; i < students.length; i++) {
            System.out.println("학생 " + (i + 1) + " 점수 = " + students[i]);
        }

        System.out.println(students);
    }

2차원 배열

row(행) column(열)

    public static void main(String[] args) {
        //2 x 3 배열
        int[][] arr = new int[2][3];
        // 0 0 0
        // 0 0 0 이렇게 초기화

//      [[1, 2, 3], [4, 5, 6]] 파이썬 문법으로 본다면

        arr[0][0] = 1; //0행 0열
        arr[0][1] = 2; //0행 1열
        arr[0][2] = 3; //0행 2열
        arr[1][0] = 4; //1행 0열
        arr[1][1] = 5; //1행 1열
        arr[1][2] = 6; //1행 2열
        
        // 1 2 3
        // 4 5 6
        System.out.print(arr[0][0] + " ");
        System.out.print(arr[0][1] + " ");
        System.out.println(arr[0][2] + " ");
        System.out.print(arr[1][0] + " ");
        System.out.print(arr[1][1] + " ");
        System.out.print(arr[1][2] + " ");
    }

 

초기값을 통한 초기화, 2중 for문을 활용한 개선 (배열과 기본적으로는 동일하다)

    public static void main(String[] args) {

        int[][] arr = new int[2][3];

        int row = arr.length;
//        int[][] arr = new int[][] {
//            {1, 2, 3},
//            {4, 5, 6}
//        };
//        int[][] arr = {
//            {1, 2, 3},
//            {4, 5, 6}
//        };

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                arr[i][j] = (i * 3) + (j + 1);
            }
        }

        for (int i = 0; i < row; i++) {
            for (int j = 0; j < 3; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }

 

+ 3차원 배열의 경우에는 면, 행, 열로 생각할 수 있다. 

int[][][] triple = new int[3][3][3];

Enhanced For (For Each)

인덱스를 사용하지 않고, 종료 조건도 없이 배열의 요소를 전부 탐색할 수 있는 편리한 반복문.

하지만 인덱싱이 필요한 경우에는 일반 반복문을 사용하는 편이 효율적이다.

    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};
        //단축키 iter

        //일반 for문
        for (int i = 0; i < numbers.length; i++) {
            System.out.print(numbers[i] + " ");
        }
        System.out.println();
        // for-each 배열의 요소를 순차적으로 순회한다.
        // numbers 배열의 각 요소에 대한 값의 복사본이 number로
        for (int number : numbers) {
            System.out.print(number + " ");
        }
    }

Scanner, Array, Switch 활용 예시

보통 객체에 담아서 데이터를 관리하겠지만, 단일 배열을 활용한 예시

import java.util.Scanner;

// 상품 등록: 상품 이름과 가격을 입력받아 저장.
// 상품 목록: 지금까지 등록한 모든 상품의 목록 출력

// 첫 화면에서 사용자에게 세 가지 선택 제시 1. 상품 등록, 2. 상품 목록, 3.종료
// 1번은 사용자로부터 상품 이름과 가격을 입력받아 배열에 저장한다.
// 2번은 배열에 저장된 모든 상품을 출력한다.
// 3. 종료를 선택하면 프로그램 종료
// 상품은 최대 10개까지 등록할 수 있다.
public class ArrayEx8 {
    public static void main(String[] args) {
        boolean active = true;

        Scanner scanner = new Scanner(System.in);
        int maxProducts = 3;

        String[] productNames = new String[maxProducts];
        int[] productPrice = new int[maxProducts];
        int productCount = 0;

        while (active) {
            System.out.print("1. 상품 등록 | 2. 상품 목록 | 3. 종료\n메뉴를 선택하세요: ");
            //숫자만 입력한다는 가정
            int option = scanner.nextInt();
            //입력 버퍼 비우기 \n
            scanner.nextLine();

            switch (option) {
                case 1:

                    if (productCount >= maxProducts) {
                        System.out.println("더 이상 상품을 등록할 수 없습니다.");
                        continue;
//                        break;
                    }
                    System.out.print("상품 이름을 입력하세요: ");
                    productNames[productCount] = scanner.next();
                    System.out.print("상품 가격을 입력하세요: ");
                    productPrice[productCount] = scanner.nextInt();

                    productCount++;
                    break;
                case 2:
                    if (productCount == 0) {
                        System.out.println("등록된 상품이 없습니다.");
                        continue;
                    }
                    for (int i = 0; i < productCount; i++) {
                        System.out.printf("%s : %d 원\n", productNames[i], productPrice[i]);
                    }
                case 3:
                    System.out.println("프로그램을 종료합니다.");
                    active = false;
                default:
                    System.out.println("잘못된 메뉴를 입력하셨습니다.");
                    break;
            }
        }
    }
}

 

 

학습 출처

김영한의 자바 입문 - 코드로 시작하는 자바 첫걸음