1. 배열(Array)

배열이 필요한 이유

package array;

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;

        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);
    }
}

실행 결과

문제점: 학생 수가 5명이면 int형 변수를 5개 선언해야 하고, 학생 수가 100명이면 int형 변수를 100개 선언해야 한다.

학생 수가 증가함에 따라 코딩 양이 비례해서 증가하는 문제 발생

→ 같은 타입의 변수를 반복해서 선언하고 반복해서 사용하는 문제를 해결하는 것이 배열

 

 

2. 배열의 선언과 생성

배열은 같은 타입의 변수를 사용하기 편하게 하나로 묶어둔 것

package array;

public class Array1Ref1 {
    public static void main(String[] args) {
        int[] students; //배열 변수 선언
        students = new int[5]; //배열 생성 (int형 변수 5개를 담을 수 있음)
        
        //변수 값 대입
        students[0] =90;
        students[1] =80;
        students[2] =70;
        students[3] =60;
        students[4] =50;


        //변수 값 사용
        System.out.println("학생1 점수: " + students[0]);
        System.out.println("학생2 점수: " + students[1]);
        System.out.println("학생3 점수: " + students[2]);
        System.out.println("학생4 점수: " + students[3]);
        System.out.println("학생5 점수: " + students[4]);
    }
}
  • int[ ] students; 배열 변수 선언. 대괄호[ ]가 들어감
  • students = new int[5]; 배열 생성. new: 새로 생성한다, int[5]: int형 변수 5개 → 총 5개의 int형 변수가 만들어짐
  • 자바는 배열을 생성할 때 그 내부값을 자동으로 초기화한다. 숫자는 0, boolean은 false, String은 null로 초기화된다.

실행 결과 (int 초기화는 0)

  • 배열 참조값 보관: students = [I@b4c966a;  int[] students 변수는 new int[5]로 생성한 배열의 참조값을 가지고 있다. 이 참조값을 통해 메모리에 있는 실제 배열에 접근하고 사용할 수 있다.
int[] students = new int[5]; //1. 배열 생성
int[] students = [I@b4c966a; //2. new int[5]의 결과로 x001 참조값 반환
students = [I@b4c966a //3. 최종 결과

 

참조값 확인 방법

System.out.println(students); // [I@b4c966a

[I: 인트형 배열

@뒤의 16진수: 참조값

 

[정리]
생성한 배열을 참조할 수 있는, 메모리의 주소를 나타내는 특별한 값이 있다.

 

 

3. 배열 사용

인덱스(Index)

배열의 위치를 나타내는 숫자 ※ index는 0부터 시작함

 

 

기본형 vs 참조형

자바의 변수 데이터 타입에는 기본형, 참조형이 있다.

  • 기본형(Primitive Type): 변수에 사용할 값을 직접 넣을 수 있는 데이터 타입                                                                ex) int, long, double, boolean
  • 참조형(Reference Type): 데이터에 접근하기 위한 참조(주소)를 저장하는 데이터 타입                                              ex) int[ ] students                                                                                                                                                            → 동적 메모리 할당; 기본형은 선언과 동시에 크기가 정해지지만, 참조형은 사용자 입력에 따라 변수의 크기가 동적으로 변해서 유연성을 제공할 수 있다.

 

4. 배열 리펙토링

리펙토링(Refactoring)

기존의 코드 기능은 유지하면서 내부 구조를 개선하여 가독성을 높이고, 유지보수를 용이하게 하는 과정

- 주로 가독성을 높이고 유지보수를 편하게 한다.- 버그를 없애거나 새로운 기능을 추가하는 행위는 아니다.
- 사용자가 보는 외부 화면은 그대 두면서 내부 논리나 구조를 개선하는 유지보수 행위이다.

 

배열 리펙토링 - 변수 값 사용

package array;

public class Array1Ref2 {
    public static void main(String[] args) {
        int[] students = new int[5]; //배열 생성 (int형 변수 5개를 담을 수 있음)
        //변수 값 대입
        students[0] =90;
        students[1] =80;
        students[2] =70;
        students[3] =60;
        students[4] =50;


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

 

  • 반복문을 사용해서 코드를 개선했다. → 리펙토링(refactoring)
  • 배열의 인덱스는 0부터 시작하기 때문에 반복문에서 i = 0을 초기값으로 사용했다.
  • students.length: 배열의 길이를 제공하는 특별한 기능. 여기서는 5가 출력됨

 

배열 리펙토링 - 초기화

package array;

public class Array1Ref3 {
    public static void main(String[] args) {
        int[] students; //배열 변수 선언
        students = new int[]{90, 80, 70, 60, 50}; //배열 생성과 초기화

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

 

 

배열 리펙토링 - 간단한 배열 생성

package array;

public class Array1Ref4 {
    public static void main(String[] args) {
        int[] students = {90, 80, 70, 60, 50}; //배열 생성과 초기화

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

 

 

 

5. 2차원 배열

1) 2차원 배열 - 시작

2차원 배열은 행(row)과 열(column)로 구성된다.

2차원 배열 선언 및 생성: int [ ] [ ] arr = new int [2] [3];    //행2, 열3

 

arr[행] [열], arr[row] [column]

 

* 그림의 2차원 배열 데이터

arr[0] [0]: 1

arr[0] [1]: 2

arr[0] [2]: 3

arr[1] [0]: 4

arr[1] [1]: 5

arr[1] [2]: 6

package array;

public class ArrayDi0 {
    public static void main(String[] args) {
        // 2X3 2차원 배열을 만든다.
        int[][] arr = new int[2][3]; //행2, 열3

        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열

        //0행 출력
        System.out.print(arr[0][0] + " "); //0열 출력
        System.out.print(arr[0][1] + " "); //1열 출력
        System.out.print(arr[0][2] + " "); //2열 출력
        System.out.println(); //한 행이 끝나면 라인을 변경한다.

        //1행 출력
        System.out.print(arr[1][0] + " "); //0열 출력
        System.out.print(arr[1][1] + " "); //1열 출력
        System.out.print(arr[1][2] + " "); //2열 출력
        System.out.println(); //한 행이 끝나면 라인을 변경한다.
    }
}

실행 결과

 

 

2) 2차원 배열 - 리펙토링1

구조 개선 - 행 출력 반복

package array;

public class ArrayDi1 {
    public static void main(String[] args) {
        // 2X3 2차원 배열을 만든다.
        int[][] arr = new int[2][3]; //행2, 열3

        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열

        for (int row = 0; row<2; row++){
            System.out.print(arr[row][0] + " "); //0열 출력
            System.out.print(arr[row][1] + " "); //1열 출력
            System.out.print(arr[row][2] + " "); //2열 출력
            System.out.println(); //한 행이 끝나면 라인을 변경한다.
        }
    }
}

 

for문을 통해 행(row)을 반복해서 접근한다.

  • row=0 의 for문이 실행되면 arr[0][0] , arr[0][1] , arr[0][2] 로 1 2 3 이 출력된다.
  • row=1 의 for문이 실행되면 arr[1][0] , arr[1][1] , arr[1][2] 로 4 5 6 이 출력된다.

실행 결과

 

구조 개선 - 열 출력 반복

package array;

public class ArrayDi2 {
    public static void main(String[] args) {
        // 2X3 2차원 배열을 만든다.
        int[][] arr = new int[2][3]; //행2, 열3

        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열

        for (int row = 0; row<2; row++){
            for (int column = 0; column <3; column++) {
                System.out.print(arr[row][column] + " ");
            }
            System.out.println(); //한 행이 끝나면 라인을 변경한다.
        }
    }
}

 

for문 2번 중첩 사용: 첫 번째 for문은 을 탐색하고, 내부에 있는 두 번째 for문은 을 탐색한다.

실행 결과

 

 

3) 2차원 배열 - 리펙토링2

구조 개선 - 초기화, 배열의 길이

package array;

public class ArrayDi3 {
    public static void main(String[] args) {
        // 2X3 2차원 배열을 만든다. (초기화)
        int[][] arr = {
                {1,2,3},
                {4,5,6}
        }; //행2, 열3

        // 2차원 배열의 길이를 활용
        for (int row = 0; row< arr.length; row++){
            for (int column = 0; column < arr[row].length; column++) {
                System.out.print(arr[row][column] + " ");
            }
            System.out.println(); //한 행이 끝나면 라인을 변경한다.
        }
    }
}
초기화
{
    {1, 2, 3},
    {4, 5, 6}
}
배열의 길이
● arr.length: 행의 길이 / { }, { } 2개의 배열 요소가 있으므로 2가 출력된다.
● arr[row].length: 열의 길이 / { } 안에 3개의 요소가 있으므로 3이 출력된다.
arr[0].length는 {1, 2, 3} 배열을 뜻한다. 이 배열에는 3개의 요소가 있다.
arr[1].length는 {4, 5, 6} 배열을 뜻한다. 이 배열에는 3개의 요소가 있다.

실행 결과

 

 

구조 개선 - 값 입력

배열에 {1, 2, 3} {4, 5, 6} 이렇게 숫자를 직접 입력하지 않고, 반복문을 활용해서 배열에 순서대로 1씩 증가하는 값을 입력하도록 변경해보자.

package array;

public class ArrayDi4 {
    public static void main(String[] args) {
        // 2X3 2차원 배열, 초기화
        int[][] arr = new int[3][3];

        int i = 1;
        // 순서대로 1씩 증가하는 값을 입력한다.
        for(int row = 0; row < arr.length; row++){
            for(int column = 0; column <arr[row].length; column++) {
                arr[row][column] = i++;
            }
        }
        // 2차원 배열의 길이를 활용
        for (int row = 0; row< arr.length; row++){
            for (int column = 0; column < arr[row].length; column++) {
                System.out.print(arr[row][column] + " ");
            }
            System.out.println(); //한 행이 끝나면 라인을 변경한다.
        }
    }
}

● 중첩된 for문을 사용해서 값을 순서대로 입력한다.

● arr[row][column] = i++;

후의 증감 연산자(++)를 사용해서 값을 먼저 대입한 다음에 증가한다.

i의 초기값이 1이므로 1을 대입시킨 뒤 i가 1만큼 증가함

※ 후의(Postfix) 증감 연산자

증감연산자를 피연산자 에 두는 경우

a++

다른 연산이 먼저 수행된 후 증감 연산이 수행된다.

b = a++; //a의 현재 값을 b에 먼저 대입하고, 그 후 a 값을 증가시킴

실행 결과

 

 

6. 향상된 for문(Enhanced For Loop) = for each문

향상된 for문 (=for each문)은 배열을 사용할 때 for문보다 더 편리하게 사용할 수 있다.

for (변수 : 배열 또는 컬렉션) {
    // 배열 또는 컬렉션의 요소를 순회하면서 수행할 작업
}
package array;

public class EnhancedFor1 {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};


        //일반 for문
        for (int i = 0; i < numbers.length; i++){
            int number = numbers[i];
            System.out.println(number);
        }
        System.out.println();

        //향상된 for문, for-each문
        for (int number : numbers){
            System.out.println(number);
        }
        System.out.println();

        //for-each문을 사용할 수 없는 경우, 증가하는 index 값 필요
        for (int i = 0; i <numbers.length; i++) {
            int number = numbers[i];
            System.out.println("number " + i + "번의 결과는: " + numbers[i]);
        }
    }
}

    

실행 결과

 

일반 for문

//일반 for문
for (int i = 0; i < numbers.length; i++){
    int number = numbers[i];
    System.out.println(number);
}

배열에 있는 값을 순서대로 읽어서  number 변수에 넣고 출력한다.

배열은 처음부터 끝까지 순서대로 읽어서 사용하는 경우가 많다. 그런데 배열의 값을 읽으려면 int i와 같은 인덱스를 탐색할 수 있는 변수를 선언해야 한다. 그리고 i < number.length와 같이 배열의 끝 조건을 지정해주어야 한다.

마지막으로 배열의 값을 하나 읽을 때마다 인덱스를 하나씩 증가해야 한다.

 

개발자 입장에서는 그냥 배열을 순서대로 처음부터 끝까지 탐색하고 싶은데, 너무 번잡한 일을 해야 한다. 그래서 향상된 for문이 등장했다.

 

향상된 for문

//향상된 for문, for-each문
for (int number : numbers){
    System.out.println(number);
}
  • 향상된 for문은 배열의 인덱스를 사용하지 않고, 종료 조건을 두지 않아도 된다. 단순히 해당 배열을 처음부터 끝까지 탐색한다.
  • :의 오른쪽에 numbers와 같이 탐색할 배열을 선택하고, :의 왼쪽에 int number와 같이 반복할 때마다 찾은 값을 저장할 변수를 선언한다. 그러면 배열의 값을 하나씩 꺼내서 왼쪽에 있는 number에 담고 for문을 수행한다. for문의 끝에 가면 다음 값을 꺼내서 number에 담고 for문을 반복 수행한다. numbers 배열의 끝에 도달해서 더 값이 없으면 for문이 완전히 종료된다.
  • 향상된 for문(for each문)은 배열의 인덱스를 사용하지 않고도 배열의 요소를 순회할 수 있기 때문에 코드가 간결하고 가독성이 좋다.

 

향상된 for문을 사용하지 못하는 경우

 

향상된 for문에는 증가하는 인덱스 값이 감추어져 있다. 따라서 int i와 같은 증가하는 인덱스 값을 직접 사용해야 하는 경우에는 향상된 for문을 사용할 수 없다.

//for-each문을 사용할 수 없는 경우, 증가하는 index 값 필요
for (int i = 0; i <numbers.length; i++) {
    int number = numbers[i];
    System.out.println("number " + i + "번의 결과는: " + numbers[i]);
}

+ Recent posts