5. 배열

메밀·2022년 11월 6일
0

자바의 정석

목록 보기
1/6

1. 배열이란?

1) 배열이란?

같은 타입의 여러 변수를 하나의 묶음으로 다루는 것

int[] score = new int[3];

변수 score는 배열을 다루는 데 필요한 참조변수일 뿐 값을 저장하기 위한 공간은 아님
변수와 달리 배열은 각 저장공간이 연속적으로 배치되어 있다.

2) 배열의 선언과 생성

// 배열 선언(배열을 다룰 참조변수 선언)
타입[] 변수이름;

타입 변수이름[];

// 배열 생성(실제 저장 공간을 생성)
변수이름 = new 타입[길이]

3) 배열의 길이와 인덱스

─ 배열의 요소와 인덱스

생략

─ 배열의 길이

배열 길이의 최대값은 int 타입의 최대값, 약 20억

길이가 0인 배열도 생성 가능

─ .length

JVM이 모든 배열의 길이를 별도로 관리 → 배열이름.length를 통해 길이 정보

배열은 한 번 생성하면 길이를 변경할 수 없으니까 배열이름.length는 상수

─ 배열의 길이 변경하기

더 큰 배열을 새로 생성
기존 배열의 내용을 새로운 배열에 복사
비용이 많이 드는 방법이므로 새 배열을 생성해야 하는 상황이 가능한 적게 발생하도록

너무 크게 잡으면 메모리 낭비니까 기존의 2배 정도의 길이로

4) 배열의 초기화

생성과 동시에 자동적으로 자신의 타입에 해당하는 기본값으로 초기화

─ 원하는 값으로 초기화하기

for문 사용 → 저장하려는 값에 일정한 규칙이 있어야지 사용 가능

int[] score = new int[] {50, 60, 70, 80, 90};
int[] score = {50, 60, 70, 80, 90};

다만 배열의 선언과 생성을 따로 하는 경우엔 생략할 수 없음

int[] score;
score = new int[] {50, 60, 70, 80, 90};
// score = {50, 60, 70, 80, 90}; // 에러
매개변수로 배열을 받는 메서드를 호출할 경우 ‘new 타입[]’ 생략 불가능
int add(int[] arr){ /* 내용 생략 */ }

int result = add(new int[] {100, 90, 80, 70, 60});
int result = add({100, 90, 80, 70, 60}); // 에러

괄호 안에 아무것도 넣지 않으면 길이가 0인 배열

─ 배열의 출력

for문 사용

Arrays.toString()

배열의 값을 바로 출력하면 타입@주소가 출력되는데, 이때의 주소는 실제 주소가 아닌 내부 주소. 실행할 때마다 달라질 수 있다.
예외적으로 char 배열은 println 메서드로 출력하면 각 요소가 구분자 없이 그대로 출력됨
char[] chArr = {'a', 'b', 'c', 'd'};
System.out.println(chArr); // abcd

5) 배열의 복사

─ for문 사용

int[] arr = new int[5];
int[] tmp = new int[arr.length * 2];

for(int i = 0; i < arr.length; i++){
		tmp[i] = arr[i];
}

arr = tmp; // 참조변수 arr이 새로운 배열을 가리키게 한다.

※ arr = tmp;

참조변수 arr과 tmp는 같은 배열을 가리키게 된다. 즉, 배열 arr과 배열 tmp는 이름만 같을 뿐 동일한 배열이다. 그리고 전에 arr이 가리키던 배열은 더이상 사용할 수 없게 된다.

→ 배열은 참조변수를 통해서만 접근할 수 있기 때문에 자신을 가리키는 참조변수가 없는 배열은 JVM의 가비지 컬렉터에 의해서 자동적으로 메모리에서 제거된다.

─ System.arraycopy()

for문은 배열의 요소 하나하나에 접근해서 복사하지만 arraycopy()는 지정된 범위의 값을 한 번에 통째로 복사한다. 각 요소들이 연속적으로 저장되어 있는 배열의 특성 때문에 이러한 처리가 가능하다.

System.arraycopy(num, 0, newNum, 0, num.length);
// num[0]에서 newNum[0]으로 num.length 개의 데이터를 복사

6. 배열의 활용

1) 총합과 평균

생략

2) 최대값과 최소값

public class ArrayMaxMin {
    public static void main(String[] args) {
        int[] score = {79, 88, 91, 33, 100, 55, 95};

        int max = score[0];
        int min = score[0]; // 배열의 첫번째 값으로 최소값을 초기화

        for(int i = 1; i < score.length; i++){
            if(score[i] > max){
                max = score[i];
            } else if (score[i] < min){
                min = score[i];
            }
        } // end of for

        System.out.println("최대값: " + max);
        System.out.println("최소값: " + min);
    }
}

3) 섞기

public class ArrayShuffle {
    public static void main(String[] args) {
        int[] numArr = new int[10];

        for (int i = 0; i < numArr.length; i++){
            numArr[i] = i; // 배열을 0~9까지의 숫자로 초기화한다.
            System.out.println(numArr[i]);
        }
        System.out.println();

        for(int i = 0; i < numArr.length; i++){
            int n = (int)(Math.random() * numArr.length); // random한 인덱스를 만듦
            int tmp = numArr[0];
            numArr[0] = numArr[n];
            numArr[n] = tmp;
        }

        for(int i = 0; i < numArr.length; i++){
            System.out.println(numArr[i]);
        }
    } // end of main
}

cf) 값을 넣는 게 아니라 인덱스로 위치만 바꾸는 것이므로 중복된 값은 생기지 않는다.
카드놀이 하려고 카드를 섞을 때 새로운 카드가 갑자기 생기지 않듯이

4) 임의의 값으로 배열 채우기

public class Lotto {
    public static void main(String[] args) {
        // 로또 번호 생성
        int[] ball = new int[45];

        // 배열의 각 요소에 1 ~ 45의 값을 저장한다.
        for(int i = 0; i < ball.length; i++){
            ball[i] = i + 1;
        }

        int tmp = 0; // 두 값을 바꾸는 데 사용할 임시 변수
        int j = 0; // 임의의 값을 얻어서 저장할 변수

        // 배열의 i번째 요소와 임의의 요소에 저장된 값을 서로 바꿔서 값을 섞는다.
        // 0 ~ 5까지 6개의 요소만 바꾼다
        for(int i = 0; i < 6; i++){
            j = (int)(Math.random() * ball.length);
            tmp = ball[i];
            ball[i] = ball[j];
            ball[j] = tmp;
        }

        // 6개 뽑기
        for(int i = 0; i < 6; i++){
            System.out.printf("ball[%d] = %d%n", i, ball[i]);
        }

    } // end of main
}

5) 정렬

정렬

6) 빈도수 구하기

import java.util.Arrays;

public class ArrayCountingNumbers {
    public static void main(String[] args) {
        // 길이가 10인 배열을 만들고 0 ~ 9 사이의 임의의 값으로 초기화
        // 저장된 각 숫자가 몇 번 반복해서 나타나는지를 배열 counter에 담은 다음 출력

        int[] numbers = new int[10];
        int[] counter = new int[10];

        for(int i = 0; i < numbers.length; i++){
            numbers[i] = (int)(Math.random() * 10); // 0 <= x < 10
        }

        for(int i = 0; i < numbers.length; i++){
            counter[numbers[i]]++;
        }

        System.out.println(Arrays.toString(numbers));
        System.out.println(Arrays.toString(counter));

    }
}

2. char 배열과 String 클래스

1) char 배열과 String 클래스

String 클래스는 char 배열에 기능(메서드)을 추가한 것

char 배열과 String 클래스의 중요한 차이: String 객체는 읽을 수만 있을 뿐 내용을 변경할 수 없다.

String str = "Java";
str = str + "8";
System.out.println(str); // Java8

문자열 str의 내용이 변경되는 것 같지만, 문자열은 변경할 수 없으므로 새로운 내용의 문자열이 생성된다. (변경 가능한 문자열을 위해선 StringBuffer를 사용해야 한다)

2) String 클래스의 주요 메서드

char charAt(int index) 해당 인덱스의 문자를 반환

int length()	// 문자열의 길이를 반환
String substring(int from, int to)	// 해당 범위의 문자열을 반환, to는 포함되지 않음
boolean equals(Object obj)	// 내용 비교
char[] toCharArray()	// 문자열을 문자 배열로 변환해서 반환

char 배열과 String 클래스의 변환

char[] chArr = {'A', 'B', 'C'};

String str = new String(chArr); // char -> string
char[] tmp = str.toCharArray(); // string -> char

3. 다차원 배열

1) 2차원 배열의 선언과 인덱스

생략

2) 2차원 배열의 초기화

향상된 for문을 사용해 2차원 배열 score의 모든 요소의 합을 구하기

for(int[] tmp : score) {
	for(int i : tmp) {
		sum += i;
	}
}

⇒ 향상된 for문으로 배열의 각 요소에 저장된 값들을 순차적으로 읽어올 수는 있지만, 배열에 저장된 값을 변경할 수는 없다.

3) 가변 배열

다차원 배열을 생성할 때 전체 배열 차수 중 마지막 차수의 길이를 지정하지 않고, 추후에 각기 다른 길이의 배열을 생성함으로써 유동적인 가변 배열 구성 가능

int[][] scores = new int[5][];
scores[0] = new int[4];
scores[1] = new int[3];
scores[2] = new int[2];
scores[3] = new int[2];
scores[4] = new int[3];

물론 중괄호를 이용하여 생성과 초기화 동시에 하는 것도 가능.

4) 다차원 배열의 활용

빙고

import java.util.Scanner;

public class Bingo {
    public static void main(String[] args) {
        final int SIZE = 5;
        int x = 0, y = 0, num = 0;

        int[][] bingo = new int[SIZE][SIZE];
        Scanner sc = new Scanner(System.in);

        // 배열의 모든 요소를 1부터 SIZE*SIZE까지의 숫자로 초기화
        for(int i = 0; i < SIZE; i++){
            for(int j = 0; j < SIZE; j++){
                bingo[i][j] = i*SIZE + j + 1;
                // [0][1] = 1
                // [1][0] = 6
                // [2][0] = 11
                // 12345
                // 678910
                // 이런식으로 저장됨
            }
        }
        
        // 배열에 저장된 값을 뒤섞는다.
        for(int i = 0; i < SIZE; i++){
            for(int j = 0; j < SIZE; j++){
                x = (int)(Math.random() * SIZE);
                y = (int)(Math.random() * SIZE);

                int tmp = bingo[i][j];
                bingo[i][j] = bingo[x][y];
                bingo[x][y] = tmp;
            }
        }

        do{
            for(int i = 0; i < SIZE; i++){
                for(int j = 0; j < SIZE; j++){
                    System.out.printf("%2d ", bingo[i][j]);
                }
                System.out.println();
            }

            System.out.println();

            System.out.printf("1 ~ %d의 숫자를 입력하세요. (종료 0)", SIZE*SIZE);
            num = sc.nextInt();

            outer:
            for(int i = 0; i < SIZE; i++){
                for(int j = 0; j < SIZE; j++){
                    if(bingo[i][j] == num){
                        bingo[i][j] = 0;
                        break outer;
                    }
                }
            }
        } while(num != 0);
    } // end for main
}

0개의 댓글