배열

kailyn·2024년 8월 26일

JAVA

목록 보기
5/17

1. 배열 개요

1. 배열 정의 및 사용 이유

1-1. 배열이란?

💡 동일한 자료형(Data Type)의 묶음이다. 연속된 메모리 공간에 값을 저장하고 사용하기 위한 용도로 사용된다. 배열은 heap 영역에 new 연산자를 통해 할당된다. 또한 배열의 길이는 최초 선언한 값으로 **“고정”** 되며, 인덱스를 통해 데이터에 접근할 수 있다.

자바에서 배열을 설 할 때 크기를 지정해야 함

1-2. 배열을 사용하는 이유

  • 만약 배열을 사용하지 않는다면 동일한 자료형을 가진 다양한 값들을 각각의 변수에 저장하여 사용해야 한다.
    (모든 변수의 이름을 사용자가 관리해야 한다.)
  • 연관된 데이터를 저장하기 위한 변수의 선언을 줄여주며반복문 등을 이용하여 계산과 같은 과정을 쉽게 처리할 수 있다.

2. 배열

1. 1차원 배열 개요

1-1. 1 차원 배열 선언

  • 배열을 선언할 때 여러가지 방법이 있다.
    1. 참조 변수만 먼저 선언하여 크기 및 값을 이후에 초기화
    2. 최초 선언 시 배열의 크기 및 값을 할당
  • 배열에 있는 값에 접근 하기 위해서는 인덱스를 이용해서 접근할 수 있다.
    인덱스는 정수(음수X)만 가능하며, 0부터 시작하기 때문에 배열의 크기를 5라고 할당하였다면 0 ~ 4 까지의 인덱스를 이용해 배열에 접근할 수 있다.

import java.util.Arrays;

public class Application1 {
    public static void main(String[] args) {
        /* 수업목표. 배열에 대해 이해하고 배열의 사용 목적을 이해할 수 있다. */
        /* 필기.
         *  배열이란?
         *    동일한 자료형의 묶음(연속된 메모리 공간에 값을 저장하고 사용하기 위한 용도) 이다.
         *    head 영역에 new 연산자를 이용하여 할당한다.
        * */

        int num1 = 10;
        int num2 = 20;
        int num3 = 30;
        int num4 = 40;
        int num5 = 50;

        int sum = 0;

        /* 설명. 5개의 변수에 있던 값을 sum에 누적해 보자. */
        sum += num1;
        sum += num2;
        sum += num3;
        sum += num4;
        sum += num5;

        System.out.println("sum = " + sum);

        /* 필기. 이와 같은 작업을 배열로 활용해 보자. */
        int[] arr = new int[5];
//        arr[0] = 10;
//        arr[1] = 20;
//        arr[2] = 30;
//        arr[3] = 40;
//        arr[4] = 50;

        /* 설명. 각 배열에 접근해 각각 값을 대입하기 */
        for (int i = 0; i < 5; i++) {
            arr[i] += 10 * (i +1);
//            System.out.println(arr[i]);
        }

        /* 설명. 각 배열에 접근해 값 불러와 출력하기 */
        System.out.println("배열의 길이: " + arr.length);
        for (int i = 0; i < arr.length; i++) {      // arr의 길이가 출력됨
            System.out.println("arr[i] = " + arr[i]);

        }

        /* 설명. 1차원 배열을 한번에 문자열로 출력할 때 간단히 출력해보기 */
        System.out.println(Arrays.toString(arr));

    }
}
// java에서 배열은 크기를 지정하고 난 후 선언하기 때문에 이미 지정한 크기보다 클 경우 오류가 발생한다.

public class Application1 {
    public static void main(String[] args) {
        
        /* 필기. 이와 같은 작업을 배열로 활용해 보자. */
        int[] arr = new int[5];
//        arr[0] = 10;
//        arr[1] = 20;
//        arr[2] = 30;
//        arr[3] = 40;
//        arr[4] = 50;

        for (int i = 0; i < 6; i++) {
            arr[i] += 10 * (i +1);
            System.out.println(arr[i]);
        }

    }
}
  • 오류

public class Application2 {
    public static void main(String[] args) {

        /* 수업목표. 배열의 사용 방법을 익혀 배열을 사용할 수 있다. */
        /* 필기.
         *  배열의 사용 방법
         *   1. 배열의 선언
         *   2. 배열의 할당
         *   3. 배열의 인덱스 공간에 값 대입
        * */

        int[] iArr;
//        char cArr[];      // 대괄호([])를 변수명 뒤에 붙여도 돌아가지만 권장되지 X

//        iArr = new int[];   // 배열은 반드시 크기를 할당해 주어야 한다.
        iArr = new int[10];

        char[] cArr = new char[5];

        /* 필기. 참조자료형 변수 출력 결과 = 자료형@16진수주소값 */
        System.out.println("iArr = " + iArr);
        System.out.println("cArr = " + cArr);

        /* 필기. hashCode()를 통해 10진수 주소값도 확인할 수 있다. */
        System.out.println("iArr = " + iArr.hashCode());
        System.out.println("cArr = " + cArr.hashCode());

        /* 필기. null값을 지닌 참조 자료형 변수(아무것도 참조하지 않을 때)를 접근 시 발생하는 에러 확인 */
        cArr = null;
        System.out.println("null을 참조할 시: " + cArr.hashCode());      // 오류 발생
    }
}
import java.util.Arrays;

public class Application3 {
    public static void main(String[] args) {

        /* 수업목표. 배열에 초기화 되는 자료형벌 기본값을 이해할 수 이싿. */
        /* 필기.
         *  값의 형태별 기본값
         *  정수: 0
         *  실수: 0.0
         *  논리: false
         *  문자: \u0000
         *  참조: null
        * */

        int[] iArr = new int[5];
        System.out.println(Arrays.toString(iArr));
        boolean[] bArr = new boolean[6];
        System.out.println(Arrays.toString(bArr));

        /* 설명. 크기 할당 시 다른 초기값을 할당하고 싶을 때 */
        int[] iArr2 = {10, 11, 12, 13, 14};         // 크기 및 초기값 한번에 할당 가능(축약형)
        int[] iArr3 = new int[] {10, 11, 12, 13, 14};

        /* 설명. 문자열도 배열로 저장해 사용할 수 있다. */
        String[] sArr = {"apple", "banana", "grape", "orange"};

        /* 설명. 다양한 출력 방법들을 살펴보자.(feat.1차원 배열) */
        /* 설명. 1. 단순 for문 사용 */
        for (int i = 0; i < sArr.length; i++) {
            System.out.println(sArr[i]);
        }

        /* 설명. 2. Arrays.toString() 사용 */
        System.out.println(Arrays.toString(sArr));

        /* 설명. 3. for-each문 사용(향상된 for문) */
        for (String str: sArr) {
            System.out.println(str);
        }
    }
}
import java.util.Arrays;
import java.util.Scanner;

public class Application4 {
    public static void main(String[] args) {

        /* 수업목표. 배열을 사용하는 예시를 이해하고 적용할 수 있다. */
        /* 필기. 5명의 자바 점수를 정수로 입력 받아서 합계와 평균을 실수(double)로 구하는 프로그램을 만들어보자. */

        int[] score = new int[5];

        Scanner sc = new Scanner(System.in);
        for (int i = 0; i < score.length; i++) {
            System.out.print((i+1) + " 번째 학생의 자바 점수를 입력해 주세요: " );
            score[i] = sc.nextInt();
        }

        System.out.println(Arrays.toString(score));     // 입력된 값 중간 확인

        /* 필기. 합계(sum) 구하기 */
        int sum = 0;
        for (int perScore : score) {
            sum += perScore;
        }

        System.out.println("합계: " + sum);

        /* 필기. 평균(avg) 구하기 */
        double avg =  sum / (double)score.length;
        System.out.println("평균: " + avg);
    }
}
import java.util.Random;

public class Application5 {
    public static void main(String[] args) {

        /* 수업목표. 배열을 사용하는 예시를 통해 카드 게임을 작성해 보자. */
        String[] shape = {"SPADE", "CLOVER", "HEART", "DIAMOND"};
        String[] cardNumbers = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "JACK", "QUEEN", "KING", "ACE"};

        int randomShapeIndex = (int)Math.random() * 4;           // 0 ~ 3
        int randomCardNumberIndex = new Random().nextInt(13);      // 0 ~ 12

//        System.out.println("당신이 뽑은 카드는 " + shape[0] + cardNumbers[0] + "카드 입니다.");
        System.out.println("당신이 뽑은 카드는 \"" + shape[randomShapeIndex]
                            + cardNumbers[randomCardNumberIndex] + "\" 카드 입니다.");
    }
}

2. 다차원 배열 개요

2-1. 2차원 배열 선언

  • 2차원 이상의 배열은 다차원 배열이라고 한다. 일부 인덱스는 또 다른 배열의 주소를 보관하는 배열 역할을 한다.
  • 즉, 2차원 배열은 1차원 배열 여러 개를 하나로 묶어서 관리하는 배열이다.
  • 더 많은 차원의 배열을 사용할 수 있지만 일반적으로는 2차원 배열보다 더 높은 차원의 배열은 사용 빈도가 극히 적다.(인지 범위 초과)
  • 2차원 배열은 [ ] 를 2개를 사용하여 표현한다. 아래 예제의 배열은 3행 4열인 2차원 배열이라고 부른다.

  • 2차원 배열에서 앞에 대괄호 안에 있는 숫자는 행, 뒤에 있는 대괄호 안에 있는 숫자는 열이라고 여겨도 무관하다.

import java.util.Arrays;

public class Application1 {
    public static void main(String[] args) {

        /* 수업목표. 다차원 배열의 구조를 이해하고 사용할 수 있다. */
        /* 필기.
         *  다차원 배열
         *    다차원 배열은 2차원 이상의 배열을 의미한다.(일반적으로는 사람의 인지 범위에 맞게 최대 3차원 정도를 고려한다.)
        * */

        int[][] iArr1;
        int[] iArr2[];              // 추천 X
        int iArr3[][];              // 추천 X

        iArr1 = new int[3][2];       // 정변 배열을 위한 선언 방식(관리하는 1차원 배열의 길이가 동일)
        iArr2 = new int[3][];       // 가변 배열을 위한 선언 방식(관리하는 1차원 배열의 길이가 다를 경우)
//        iArr3 = new int[][];      // 컴파일 에러 발생

      /* 설명. 정변 배열은 이미 1차원 배열들이 생성되어 지정되어 있다. */
        int num = 0;
        for (int i = 0; i < iArr1.length; i++) {            // 1차원 배열을 고르는 for문
            for (int j = 0; j < iArr1[i].length; j++) {     // 선택된 1차원 배열의 길이만큼 반복하는 for문
                iArr1[i][j] = num++;
            }
            System.out.println(Arrays.toString(iArr1[i]));
        }

        /* 설명. 가변 배열은 아직 1차원 배열들이 생성되어 있지 않다.(NullPointerException도 발생 가능) */
        int length = 1;
        for (int i = 0; i < iArr2.length; i++) {
            iArr2[i] = new int[++length];                   // 안쪽 for문 돌기 전에 관리한 배열 만들어주기
            for (int j = 0; j < iArr2[i].length; j++) {     // 관리할 배열이 없어서 컴파일 에러 발생
                iArr2[i][j] = num++;
            }
            System.out.println(Arrays.toString(iArr2[i]));
        }
    }
}
import java.util.Arrays;

public class Application2 {
    public static void main(String[] args) {
        int[][] iArr = new int[][]{{1, 2, 3, 4, 5,}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}};
        int[][] iArr2 = {{1, 2, 3, 4, 5,}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}};

        /* 설명. 내가 2차원 배열 출력을 커스터마이징해서 활용한 출력 */
        for (int i = 0; i < iArr.length; i++) {
            for (int j = 0; j < iArr[i].length; j++) {
                System.out.println("iArr[" + i + "][" + j + "] = " + iArr[i][j] + " ");
            }
            System.out.println();
        }

        /* 설명. Arrays.toString을 활용한 출력 */
        for (int i = 0; i < iArr2.length; i++) {
            System.out.println(Arrays.toString(iArr2[i]));

        }
    }
}

3. 배열의 복사

1. 배열의 복사 개요

1-1. 배열의 복사란?

💡 자바에서는 배열를 복사하는 유형으로 얕은 복사와 깊은 복사가 있다. 1. 얕은 복사(shallow copy) : stack의 주소값만 복사 2. 깊은 복사(deep copy) : heap의 배열에 저장된 값을 복사

1-2. 복사의 종류

💡 배열의 복사 종류로는 2가지가 있다. 1. 얕은 복사(shallow copy) : stack 의 주소값만 복사 2. 깊은 복사(deep copy) : heap의 배열에 저장된 값을 복사

2. 얕은 복사 개요

2-1. 얕은 복사란?

💡 얕은 복사는 stack에 저장되어 있는 배열의 주소값만 복사한다는 것이다. 따라서 두 개의 레퍼런스 변수는 동일한 배열의 주소값을 가지고 있다. 하나의 레퍼런스 변수에 저장된 주소 값을 가지고 배열의 내용을 수정(값 변경) 을 하게 되면 다른 레퍼런스 변수로 배열에 접근했을 때도 동일한 배열을 가리키고 있기 때문에 변경된 값이 반영되어 있다.

  • 얕은 복사를 도식화한 그림을 보면 알 수 있듯이 얕은 복사는 레퍼런스 변수 안에 담긴 주솟값을 새로운 레퍼런스 변수에 복사하는 것이다.
public class Application1 {
    public static void main(String[] args) {
        /* 수업목표. 배열의 복사 개념 중 얕은 복사에 대해 이해할 수 있다. */
        /* 필기.
         *  배열의 복사에는 크게 두 가지 개념이 있다.
         *  1. 얕은 복사(shallow copy): stack의 주소값만 복사
         *  2. 깊은 복사(deep copy): heap의 배열에 저장된 값을 복사
        * */

        int[] originArr = {1, 2, 3};
        int[] copyArr = originArr;              // 참조 주소 값 복사(얕은 복사)

        System.out.println(Arrays.toString(copyArr));

        copyArr[2] = 100;
        System.out.println(Arrays.toString(originArr));     // 카피 배열에서 배열값을 바꾸면 원본 배열에서도 바뀜
    }
}
  • 결과


4. 깊은 복사 개요

4-1. 깊은 복사란?

💡 깊은 복사는 heap에 생성된 배열이 가지고 있는 값을 또 다른 배열에 복사를 해 놓은 것이다. 서로 같은 값을 가지고 있지만, 두 배열은 서로 다른 배열이기에 하나의 배열에 변경을 하더라도 다른 배열에는 영향을 주지 않는다.

  • 깊은 복사는 얕은 복사와 달리 새롭게 할당한 합 영역에 기존 배열의 값을 복사한 후 새롭게 생성된 배열의 주소값을 넘겨주는 것이다.

import java.util.Arrays;

public class Application2 {
    public static void main(String[] args) {

        /* 수업목표. 깊은 복사에 대해 이해할 수 있다. */
        /* 필기.
         *  깊은 복사를 하는 방법은 4가지가 있다.
         *  1. for문을 이용한 동일한 인덱스 값을 일일히 복사
         *  2. Object의 clone()을 이용한 복사(사용 빈도 높음)
         *  3. System의 arraycopy()를 이용한 복사
         *  4. Arrays의 copyOf()를 이용한 복사
        * */

        int[] originArr = new int[]{1, 2, 3, 4};
        print(originArr, "원본");

        /* 목차. 1. for문 활용 */
        int[] copyArr1 = new int[originArr.length];
        for (int i = 0; i < originArr.length; i++) {
            copyArr1[i] = originArr[i];
        }
        print(copyArr1, "for문을 사용한 사본");

        /* 목차. 2. clone()를 이용한 복사 */
        int[] copyArr2 =originArr.clone();
        print(copyArr2, "clone()을 이용한 사본");

        /* 목차. 3. arraycopy()를 이용한 복사 */
        int[] copyArr3 = new int[originArr.length + 3];
        System.arraycopy(originArr,0, copyArr3, 3, originArr.length);
        print(copyArr3, "arraycopy()을 이용한 사본");

        /* 목차. 4. copyOf()를 이용한 복사 */
        int[] copyArr4 = Arrays.copyOf(originArr, 2);       // 원본의 처음부터 원하는 길이까지만 복사 가능
        print(copyArr3, "copyOf()을 이용한 사본");

    }

    private static void print(int[] arr, String desc) {              // originArr -> arr로 얕은 복사가 발생함

        System.out.println("============" + desc + "============");

        /* 설명. 전달받은 배열의 주소값 출력 */
        System.out.println("넘어온 배열의 hashCode: " + arr.hashCode());

        /* 설명. 전달받은 배열의 값 출력 */
        System.out.println(Arrays.toString(arr));
    }
}
profile
나는 할 수 있다...!

0개의 댓글