본문 바로가기

LECTURE/# java basic

[초급 JAVA]자바 배열 (단일차원배열/다중배열/이중배열) - 선언 & 초기화

반응형

자바 배열 (단일차원배열/다중배열/이중배열) - 선언 & 초기화

Programming

 
ArrayExam.java

package array;
public class ExamArray {
public static void main(String[] ar) {
// 배열이란 동일한 자료형으로 선언된 데이터 공간을
// 메모리 상에 연속적으로 나열하여 데이터 관리의 효율성을 높이는 것입니다.
// 배열의 종류에는 단일차원 배열과 다 차원 배열이 있습니다.
/* 단일차원배열 */
// 단일차원배열이란 한마디로 1차원적인 데이터의 나열입니다.
// 단일차원배열은 두가지방법으로 선언 가능합니다.
// 1.자료형[] 배열명;
int[] arr_1;
// 2.자료형 배열명[];
@SuppressWarnings("unused")
int arr_2[];
// 단일 차원 배열은 두가지 방법으로 초기화가능합니다.
// 1.배열명 = new 자료형[갯수];
arr_1 = new int[10];
// 2.배열명 = new 자료형[]{초기값,초기값...};
arr_2 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 당연히 선언과 초기화를 동시에 할 수 있습니다.
// 자료형[] 배열명 = {초기값,초기값...};
@SuppressWarnings("unused")
int[] arr_4 = new int[10];
@SuppressWarnings("unused")
int[] arr_3 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// arr_1은 int자료형이 들어갈 수 있는 공간(객체) 10개를 가지고있는 배열 객체입니다.
// 10개의 공간 모두 빈 공간으로 default 값으로 초기화되어있습니다.(int자료형의default값은 0입니다.)
// arr_1[0]과 arr_1[1]에 값을 넣어보죠.
arr_1[0] = 10;
arr_1[1] = 11;
System.out.println("arr_1[0] : " + arr_1[0]);
System.out.println("arr_1[1] : " + arr_1[1]);
System.out.println("arr_1[2] : " + arr_1[2]);
// arr_1[0]이란 arr_1의 배열 0번째 객체라는 뜻입니다.
// arr_1이란 배열객체는 heap영역에 어떠한 공간 하나를 참조하고있습니다.
// 그리고 arr_1의 크기 만큼 연속된 숫자로 방을 만들죠. int형은 4byte 자료형이니
// 만약 arr_1이 100번 주소를 참조하고있고 크기가 5라면
// arr_1[0]->100 arr_1[1]->104,arr_1[2]->108...arr_1[4]->116
// 이런식으로 각자의 크기를 가지고 나열됩니다.값이 없다면 0으로 초기화되어있겠죠.
// 위에 출력 결과를 이제 이해하실수 있겠습니까?
// arr_[0]과 arr_1[1]에는 10과 11이란 값을 넣었고 arr_1[2]에는 아무값도 넣지
// 않았으니 10, 11, 0 이 순서대로 출력된겁니다. 만약
// System.out.println("arr_1[10] :"+arr_1[10]);
// 를 출력한다면 ArrayIndexOutOfBoundsException : 10 이라는 오류가 뜹니다.
// 배열을 선언 할 때 10개의 공간만 가지도록 초기화했기때문에 배열은
// arr_1[0]~arr_1[9]까지 존재하기때문에 범위를 벗어났다는 오류메시지가 뜨는겁니다.
/* 다차원배열 */
// 다차원 배열에는 대표적으로 이중배열이 있습니다.
// 선언
// 자료형[][] 배열명;
@SuppressWarnings("unused")
double[][] arr_double_1;
// 자료형 [] 배열명 [];
double[] arr_double_2[];
// 자료형 배열명[][];
double arr_double_3[][];
// 다차원 배열 초기화
// 배열명 = new 자료형[개수][개수];
arr_double_1 = new double[3][5];
// 배열명 = new 자료형[][]{{...},{...}};
arr_double_2 = new double[][] { { 1.0, 2.0, 3.0 }, { 1.0, 2.0, 3.0 } };
// 배열명 = new 자료형[개수][]; -동적배열
arr_double_3 = new double[3][];
// 이중배열을 이해하면 삼중배열 사중배열 역시 마찬가지로 이해할 수 있습니다.
// 그러나 삼중배열 이상부터는 잘쓰는 편은 아니며, 굳이 쓸 이유도 없습니다. 코드가 매우복잡해지기때문입니다.
// arr_double_1배열객체는 new double[3][5];로 초기화되었습니다.
// 무슨의미일까요?
// 단일 차원 배열이 하나의 주소값을 참조하여 그주소값부터 배열의 크기만큼 일열로 나열된 거라면
// 이중 배열은 여러개의 주소를 참조하여 여러 열을 나열시킨겁니다.
// double[3][5]라는 뜻은 크기 5개의 열이 3줄 있다는 뜻인거지요. 말로는 이해가안갑니다.
// 포스팅에서 그림으로 그려놓을테니 참고하세요.
// arr_double_1이 크기만 정해서 초기화하는거라면
// arr_double_2를 초기화하는 방법은 크기와 값을 동시에 초기화하는 겁니다.
// arr_double_2 를 arr_double_1처럼 바꿔 선언하면 이렇게되죠.
arr_double_2 = new double[2][3];
for (int i = 0; i < arr_double_2.length; i++) {// 배열명.lenhth 를 하면 배열의 크기를 구할수있습니다.
for (int j = 1; j < arr_double_2[i].length + 1; j++) {
arr_double_2[i][j - 1] = j;
System.out.print(arr_double_2[i][j - 1] + " ");
}
System.out.println();
}
// 크기가 정해져있고 값이 정해져있다면 처음부터 저렇게 선언해놓는 것이 편하고 메모리도 효율적으로
// 관리 할 수 있죠. 그러나 그런 경우는 그렇게 많지않습니다.
// 몇개의 데이터가 어떻게 생기고 줄어들지 모르는 경우가 훨씬 많죠. 그래서 동적 할당이라는것이있습니다.
// arr_double_3=new double[3][]; 으로 초기화 한다는 것은
// 3개의 줄을 세울건데 몇줄씩 슬지는 정해놓지않고 오는거봐서 세우겠다. 라는 의미입니다.
for (int i = 0; i < arr_double_3.length; i++) {
int rand = (int) (Math.random() * 10 + 1);//random함수입니다.0.0부터 0.9까지 난수를 생성합니다.
arr_double_3[i]=new double[rand];//double_3[i]를 double[rand]만큼 크기를 주겠다.라는의미입니다.
for (int j = 0; j < arr_double_3[i].length; j++) {
arr_double_3[i][j] = j;
System.out.print(arr_double_3[i][j] + " ");
}
System.out.println();
}
}
}

배열

배열이란?

저는 개인적으로 배열을 같은 속성을 가진 덩어리를 줄세우는 과정이라고 정의하고 싶습니다.  

이렇게 원이라는 속성을 가지고 3개를 넣을 수 있는공간을 가진 원배열에 원 3개를 줄세우고, 네모라는 속성을 가지고 3개를 넣을 수 있는 공간을 가진 네모배열에 네모 3개를 줄세우는 것이 배열입니다. 

원이라는 속성으로 정의된 배열에 네모가 들어가면 오류가 나게됩니다. 그렇기때문에 배열을 선언 할 때 자료형을 반드시 제시해주어야 합니다. 

배열을쓰면 무슨 장점이 있을까요? 예를 들어 1부터 10까지의 int형 데이터가 있다고 가정합니다. 이 데이터들을 int형 객체에 담아서 출력을 하려고 할 때 일반적으로는 하나하나 객체를 생성하고 그 객체에 1부터 10까지 따로따로 넣어줘야 합니다. 

1
2
3
4
5
6
7
8
int a = 1;
int b = 2;
int c = 3;
int d = 4;
.
.
.
int j = 10;
cs

그런데 이건 너무 비효율적입니다. 코딩의 길이도 늘어날 뿐더러 데이터 관리도 힘들죠. 게다가 내부적으로는 객체를 여러군데에 무작위로 생성하고 그걸 기억하려 하다보니 리소스도 더 많이 차지하게됩니다. 이런 경우에 배열을 쓰면 어떻게 될까요?

int a [10= {1,2,3,4,5,6,7,8,9,10}; 

한줄이면 코딩을 할 수 있고 원한다면 for문으로 간단하게 데이터를 처리할 수도있습니다. 또한 내부적으로는 배열 a의 첫 시작부분인 a[0]의 주소만 기억하면 나머지는 차례대로 줄을 서있으니 몇번째인지만 안다면 바로 찾을 수 있으니 리소스도 절약 할 수 있습니다. 배열에 대해 알아야겠다는 의지가 불타오르시나요? ^^ 배열은 프로그램에 아주 중요한 개념 중 하나이니 반드시 알고 넘어가야겠습니다. 

배열의 종류에는 단일차원배열과 다중배열이 있습니다. 이제부터 하나하나 저와함께 알아가보도록 하죠.

단일차원배열

단일차원배열이란 ?

제가 처음에 배열을 무엇이라고 생각한다고 했지요? 맞습니다. 줄서기입니다. 단일차원배열이란 어려울게없습니다. 그냥 한줄서기를 하는 배열입니다. 아무리 길어도 한줄로서야만 하는 녀석이죠. 

10개의 int형 데이터를 관리해야 할 일이 있어서 배열을 쓰는 상황이라고 생각해봅시다. 배열을 만들 때 크기를 지정하여 초기화 할 수 있는데, 10개보다 작은 공간의 배열을 만들어도 안되고, 쓸때없이 10개보다 큰 공간의 배열을 만들어 리소스를 낭비 할 필요도 없습니다. 개수가 정해져있는 데이터를 배열로 처리 할때는 데이터의 크기만큼 배열을 지정해 주면됩니다. 

int [] A = new int[10]; 으로 공간을 선언만 하였을 때는 그림과같이 10개의 공간이 만들어집니다. 이 공간에 값을 넣어보겠습니다.

1
2
3
A[0= 101;
A[1= 102;
A[2= 103;
cs

A[0],A[1],A[2]에 차례대로 값을 넣으니 공간에 값이 제대로 들어갑니다. 그러면 값을 넣지않은 공간에는 무슨 값들이 들어있을까요? 자료형마다 다른 default 값이 들어있습니다. 

short,int,double,float형의 default값은 0

String 형의 default값은 null

char 형의 default 값은 공백

배열의 개념 중 가장 중요한 부분은 배열의 주소할당입니다. A[5]의 값을 가지고 올 때, java는 A[5]의 주소를 기억하고 있다가 값을 가지고 올까요? 답을 먼저 말씀드리자면 아닙니다. 배열이 선언될때 java는 배열을 heap 영역 어딘가에 주소를 할당해줍니다. 할당된 주소를 이해하기 쉽게 100 이라고 하겠습니다.  


int 자료형의 크기는 4byte이므로 한공간의 크기역시 4byte로 계산해봅시다. A배열의 첫시작인 A[0]의 시작 주소는 처음 할당받은 100이됩니다. 그리고 A[0]이 끝나는 지점은 104이므로 A[1]의 시작주소는 104가됩니다. A[9]의 시작주소는 어떻게될까요? 네 그렇습니다. 0보다 9는 9만큼 크고 한 공간의 크기는 4이므로 9*4 =36 만큼 떨어져있고 , 시작주소가 100이므로 100+36=136 A[9]의 시작주소는 136이라는 점을 쉽게 알 수 있습니다. 이렇게 컴퓨터는 A배열의 시작 주소만 알고있다면, A배열의 어떤요소의 값을 바로 구해낼 수 있습니다. 

지금까지는 처리해야 할 데이터의 갯수가 정해져있는 경우에 배열을 쓰는 방법에대해서 말했습니다. 그렇다면, 처리해야할 데이터의 갯수가 일정하지않고 매순간 변동이 있는 값이라면 어떻게 해야할까요? 안타깝게도 단일차원배열에서는 상황에따라 늘어나고 줄어나는 배열을 만들 수 없습니다. 대신 ArrayList 같은 클래스를 사용하면 되지만, 아직은 배우지않았으니 범위를 크게잡아서 선언해놓고 사용합시다.

다중배열
다중배열도 어렵지 않습니다. 다중배열은 두 줄 이상 줄서기를 하는 놈입니다. 

이런 식으로 A배열에 두개 이상의 줄이 서있다면 다중배열이라합니다. 위 그림을 코드로 나타내면 이렇게됩니다.

1
int A[][] = new int [2][10];
cs

그렇습니다. 앞에 있는 대괄호 안에 숫자 2는 줄의 갯수를 의미합니다. 그리고 뒤에 있는 대괄호의 숫자는 줄의 크기를 의미하죠. 그러니까 두줄로 줄을 서는데 한줄에 최대 10개씩 설 수 있다 라는 의미입니다. 그러면 int A[][][] = new int [2][2][2] 는 어떻게 구성이 될지 감이 오실까요? 안오시겠지만 한번 생각해보세요. 별거없습니다. 생각해보시고 모르시겠다면 댓글 남겨주세요 ^^ 3차원이상의 다중배열은 다루지않겠습니다. 잘 안쓰니까요^^; 그러나 한번쯤 생각은 해볼필요가 있습니다. 

다중배열에서도 저장방식이 중요한데, 단일차원배열과 별다를게없습니다. 처음 선언할때 각각의 줄의 시작주소를 기억하여 원하는 값을 가져오는거지요. ArrayExam.java 에 주석으로 설명한 동적배열을 초기화하는 방법에대해서는 더이상 설명할 부분이 없기때문에 쓰지않겠습니다. 주석을 보시고 한번 코딩해보시면됩니다. 그림은 그려놓을게요 ^^

*그림과 ArrayExam.java 소스내용과는 상관없습니다. 그러나 같은 맥락이므로 이해하실 수 있습니다.

다음 포스팅에서는 지금까지 배운 내용으로만으로 간단한 프로그램을 짜보도록 하겠습니다. 감사합니다.



반응형