배열(Array)이란 같은 타입의 여러 값을 효과적으로 관리하기 위해서 사용하는데요.
배열을 알아보기 전에 메모리 구조부터 알아볼게요.
자바는 JVM(자바 가상 머신)을 통해 모든 프로그램이 실행됩니다.
즉, JVM은 자바 코드를 실행시키기 위한 가상의 기계라고 볼 수 있는데요.
자바로 작성된 모든 프로그램은 자바 가상 머신에서만 실행이 될 수 있습니다.
자바 프로그램을 실행시키기 위해서는 JVM이 반드시 설치가 되어있어야 하죠.
자바 프로그램이 실행되면 JVM은 운영 체제로부터 해당 프로그램을 수행할 수 있도록 메모리를 할당받습니다.
각 메모리의 영역은 static 영역, stack 영역, heap 영역으로 구분하고 있습니다.
먼저 static 영역에는 자바 프로그램에서 사용되는 클래스에 대한 정보와 class 변수(static 변수)가 저장되는 영역입니다.
JVM은 자바 프로그램에서 사용되는 클래스의 파일을 읽어 해당 클래스에 대한 정보를 스태틱 영역에 저장합니다.
stack 영역은 메소드가 호출될 때 해당 메소드의 지역변수와 매개변수를 stack 영역에 저장합니다.
이후 메소드의 호출이 완료되면 소멸합니다.
이러한 방식을 후입선출(LIFO : Last In First Out) 방식이라고 하며 리포라고도 부릅니다.
heap 영역은 자바 프로그램의 모든 인스턴스 객체가 저장되는 영역입니다.
new 키워드가 사용되어 객체가 생성되면 해당 객체의 정보를 heap 영역에 저장합니다.
자, 다시 배열로 돌아오면 배열은 같은 타입의 어려 값을 효과적으로 관리하기 위해 사용됩니다.
배열에서 위치를 가리키는 숫자를 인덱스(index)라고도 합니다.
이런 인덱스의 첫 시작은 1이 아닌 0입니다. 또한 인덱스는 음수는 포함할 수 없습니다.
배열을 선언하는 다양한 방법이 있습니다.
// 방법 1.
int[] a; //선언
a = new int[5]; //정의
a[0] = 1; //초기화(값넣는것)
a[1] = 2;
a[2] = 3;
a[3] = 4;
a[4] = 5;
// 방법 2.
int[] b = new int[] {1,2,3,4,5}; //선언 정의 초기화
//방법 3.
int[] c = {1, 2, 3, 4, 5}; //선언 초기화
3개의 배열의 길이가 5이며 각 인덱스에 들어있는 값이 같습니다.
선언하는 방식만 달라졌으며 new 키워드가 사용된 것을 볼 수 있습니다.
System.out.println(a.length);
System.out.println(b.length);
System.out.println(c.length);
a[0], b[0], c[0] 모두 값이 1이며 a[4], b[4], c[4] 모두 값이 5이며 길이가 5로 정의되어 있는 이 3개의 배열 모두 배열의 길이는 바뀔 수 없습니다.
5로 정의가 되어있기 때문에 5로 고정이 됩니다.
그러면 a[0] + b[1] + c[2]의 값은 무엇일까요?
int sum = a[0] + b[1] + c[2];
System.out.println(sum);
위의 명령을 실행하면 6이 나오게 됩니다.
System.out.println(c);
c를 출력해보면 어떨까요?
배열로 선언되어 있는 c를 출력하게 되면 해당 배열의 주소값이 나옵니다.
c 배열의 주소값 안에 들어있는 값을 직접 출력하려면 어떻게 해야 될까요?
System.out.println(Array.toString(c));
해당 명령을 실행하면 c 배열 안의 값이 직접 출력됩니다.
조금만 쉽게 설명해볼까요?
int[] a = new int[5];
a[0] = 1;
a[1] = 2;
a[2] = 3;
a[3] = 4;
a[4] = 5;
그림으로 표현하면 다음과 같습니다.
a라는 주소에 a[0] 방에는 1이 들어있고 a[1]번 방에는 2가 들어있고 a[4]번 방에는 5가 들어있습니다.
방은 0번부터 4번까지 있지만 방의 개수는 5개죠?
즉, 배열의 길이는 5지만 인덱스 값은 0부터 4까지입니다.
// 방법 1.
int[] a; //선언
a = new int[5]; //정의
a[0] = 1; //초기화(값넣는것)
a[1] = 2;
a[2] = 3;
a[3] = 4;
a[4] = 5;
// 방법 2.
int[] b = new int[] {5,4,3,2,1}; //선언 정의 초기화
// 방법 3. int[] c = {6, 7, 8, 9, 10}; //선언 초기화
System.out.println(a.length); //a의 길이
System.out.println(b.length); //b의 길이
System.out.println(c.length); //c의 길이
int sum = a[0] + b[1] + c[2];
System.out.println(sum);
System.out.println(c); //c의 주소값이 출력됨
System.out.println(Arrays.toString(c)); //해당 주소값의 값을 직접 출력해줌
배열은 또한 다차원으로 선언할 수도 있습니다.
배열이 2개 이상이 될 수가 있다고 이해하시면 됩니다.
선언 방식을 볼까요?
//방법 1.
int[][] a = new int[3][2]; //큰 주소3개 그 주소 안에 주소2개씩
a[0][0] = 1;
a[0][1] = 2;
a[1][0] = 3;
a[1][1] = 4;
a[2][0] = 5;
a[2][1] = 6;
//방법 2.
int [][] b = new int[3][]; //큰 주소를 3개 만들어놨는데 그 안에주소는 몇개인지 모름
b[0] = new int[3]; //1번 큰주소 안에 작은주소 3개
b[1] = new int [5]; //2번 주소 안에 작은주소 5개
b[2] = new int [1]; //3번 큰 주소 안에 1개
//방법 3. int[][] c = new int[][] {
{1, 2},
{3, 4 ,5},
{6, 7, 8, 9},
{10}
};
//int[][] c = new int[][] {{1, 2}, {3, 4 ,5}, {6, 7, 8, 9}, {10}};
선언을 하는 방식은 다양하지만 어떤 식으로 선언하는지 아시겠나요?
위와 같이 선언된 배열을 2차원 배열이라고 합니다.
3차원 4차원도 될 수 있지만 복잡해지기도 하고 실제로는 잘 안 쓴다고 합니다.
int[][] a = new int[3][2];
a[0][0] = 1;
a[0][1] = 2;
a[1][0] = 3;
a[1][1] = 4;
a[2][0] = 5;
a[2][1] = 6;
2차원 배열로 정의된 a는 a 배열(주소) 안에 a[0], a[1], a[2]의 방이 들어있습니다.
하지만 2차원 배열이기 때문에 방안에 또 방이 있습니다.
2차원 배열의 구조를 잘 아시겠나요? (그림 그리려니까 설명하려니까,,,,)
자 그럼 배열 안에 또 배열이 있는데 이것도 Arrays.toString()으로 값을 출력할 수 있을까요??
2차원 배열에서는 조금 다릅니다.
System.out.println(Arrays.toString(a)); //배열 주소안의 내용 출력
System.out.println(Arrays.deepToString(a)); //다중배열일떄 주소안의 내용충력
Arrays.toString()을 사용할 경우 배열 안의 주소가 출력됩니다.
2차원 배열의 직접 값을 출력하기 위해서는 Arrays.deepToString()을 사용해야 합니다.
/*1번
* a b c d e f
* g h i j k l
* m n o p q r
* s t u v w x
* y z
* 출력!
* 단, 일차원 배열에, 반복문을 사용하여 알파벳을 저장한 후에 출력하자.
* char[] ar = {'a','b','c' ... 'z'}; 금지
*/
/*2번
* 1 4 7
* 2 5 8
* 3 6 9
*
* 모양의 이차원 배열을 만들어서 출력하자.
*/
/*3번
* 1 2 3 4 5
* 10 9 8 7 6
* 11 12 13 14 15
* 20 19 18 17 16
* 21 22 23 24 25
*
* 모양을 이차원 배열 사용하여 출력하자.
*/
어떤 형태의 코드도 좋습니다! 배열에 값을 직접 넣지 말고 위의 출력 결과가 나오게 코드를 짜보시겠어요?!
1번.
char[] alp = new char [26];
for(int i = 0; i < alp.length; i++) {
alp[i] = (char)('a'+ i);
System.out.printf("%s ",alp[i] );
//System.out.println(Array.toString(alp));
if((i+1) % 6 == 0) {
System.out.println();
}
}
char[] alp = new char [26];
길이가 26인 char 타입의 alp라는 변수가 선언되었습니다.
for(int i = 0; i < alp.length; i++) {
alp[i] = (char)('a'+ i);
System.out.printf("%s ",alp[i] );
//System.out.println(Array.toString(alp));
if((i+1) % 6 == 0) {
System.out.println();
}
}
반복문은 alp의 길이만큼 반복이 됩니다. 즉, 26번 반복하게 됩니다.
alp의 i번지에는 알파벳이 들어갑니다. i가 0일떄는 alp[0]에 'a'라는 문자가 담기며 i가 1일떄는 alp[1]에 'b'라는 문자가 담깁니다.
alp[i] = (char)('a'+ i); 에서의 연산은 ASCII CODE를 통해 하게 됩니다.
또한 for문 안에 있는 if문의 조건으로 인해 한줄에 알파벳을 6개만 출력합니다.( 알파벳 6개를 출력한후 줄 바꿈을 합니다 )
2번.
int[][] a = new int[3][3];
int cnt = 1;
//만들기
for(int i = 0; i < a.length; i++) {
for(int j = 0; j < a[i].length; j++) {
a[j][i] = cnt++;
}
}
//출력하기
for(int i = 0; i < a.length;i++) {
for(int j = 0; j < a[i].length; j++) {
System.out.printf("%2d", a[i][j]);
}
System.out.println();
}
int[][] a = new int[3][3];
int cnt = 1;
이차원 배열 a가 선언되어 있습니다.
for(int i = 0; i < a.length; i++) {
for(int j = 0; j < a[i].length; j++) {
a[j][i] = cnt++;
}
}
해당 코드의 경우 숫자 저장을 위한 반복문과 출력을 위한 반복문을 따로 만들어야합니다.
1 4 7
2 5 8
3 6 9
의 모양으로 출력하려면 먼저 숫자를 변수에 담아놓고 출력을 해야합니다.
변수에 저장하면서 출력을 같이할수가 없어요!
i = 0 / j = 0 일때
a[j][i] = a[0][0] = 1
i = 0 / j = 1 일때
a[j][i] = a[1][0] = 2
i = 0 / j = 2 일때
a[j][i] = a[2][0] = 3
i = 1 / j = 0 일때
a[j][i] = a[0][1] = 4
i = 1 / j = 1 일때
a[j][i] = a[1][1] = 5
i = 1 / j = 2 일때
a[j][i] = a[2][1] = 6
i = 2 / j = 0 일때
a[j][i] = a[0][2] = 7
i = 2 / j = 1 일때
a[j][i] = a[1][2] = 8
i = 2 / j = 2 일때
a[j][i] = a[2][2] = 9
for(int i = 0; i < a.length;i++) {
for(int j = 0; j < a[i].length; j++) {
System.out.printf("%2d", a[i][j]);
}
System.out.println();
}
이렇게 a배열에 저장된 값을 해당 반복문에서 출력하게 됩니다.
i = 0 / j = 0 일때
a[0][0]을 출력합니다.
위에서 a[0][0]에는 1이 저장되어있습니다.
i = 0 / j = 1 일때
a[0][1]을 출력합니다.
위에서 a[0][1]에는 4가 저장되어있습니다.
i = 0 / j = 2 일때
a[0][2]을 출력합니다.
위에서 a[0][2]에는 7이 저장되어있습니다.
줄바꿈...
i = 1 / j = 0 일때
a[1][0]을 출력합니다.
위에서 a[1][0]에는 2이 저장되어있습니다.
i = 1 / j = 1 일때
a[1][1]을 출력합니다.
위에서 a[1][1]에는 5이 저장되어있습니다.
i = 1 / j = 2 일때
a[1][2]을 출력합니다.
위에서 a[1][2]에는 8이 저장되어있습니다.
줄바꿈...
i = 2 / j = 0 일때
a[2][0]을 출력합니다.
위에서 a[2][0]에는 3이 저장되어있습니다.
i = 2 / j = 1 일때
a[2][1]을 출력합니다.
위에서 a[2][1]에는 6이 저장되어있습니다.
i = 2 / j = 2 일때
a[2][2]을 출력합니다.
위에서 a[2][2]에는 9이 저장되어있습니다.
3번.
int cnt = 1;
for(int i = 0; i < a.length; i++) {
if(i%2==0) {
for(int j = 0; j < a[i].length; j++) {
a[i][j] = cnt++;
}
} else if(i%2==1) {
for(int j = a.length-1; j >= 0; j--) {
a[i][j] = cnt++;
}
}
}
for(int i = 0; i < a.length; i++) {
for(int j = 0; j < a[i].length; j++) {
System.out.printf("%3d", a[i][j]);
}
System.out.println();
}
해당 코드에서도 값을 저장하는 반복문과 출력하는 반복문을 따로 만들어야합니다.
우선 첫번째 반복문에는 for문안에 또 다른for문이 2개가 들어있으며 조건문(if문)을 통해 줄바꿈을 할때마다 저장되는 공간이 달라집니다.
먼저 나온 반복문에서
if(i%2==0)
i의 나머지가 0인경우
for(int j = 0; j < a[i].length; j++) {
a[i][j] = cnt++;
}
해당 반복문을 통해 배열에 숫자가 저장됩니다.
정상적인 순서로 저장되게 됩니다.
반면 i의 나머지가 1인경우
for(int j = a.length-1; j >= 0; j--) {
a[i][j] = cnt++;
}
해당 반복문을 통해 배열에 숫자가 저장됩니다.
이 반복문에서는 역순으로 배열에 숫자가 저장되게 됩니다.
for(int i = 0; i < a.length; i++) {
for(int j = 0; j < a[i].length; j++) {
System.out.printf("%3d", a[i][j]);
}
System.out.println();
}
따라서 이렇게 저장된 배열a를 출력하면
1 2 3 4 5
10 9 8 7 6
11 12 13 14 15
20 19 18 17 16
21 22 23 24 25
해당 모양으로 콘솔창이 출력되게됩니다!
'Java 관련 > Java' 카테고리의 다른 글
[Java] Random()을 이용한 로또 코드(lotto code) (0) | 2021.10.20 |
---|---|
[Java] 얖은값 복사(Shallow copy), 깊은값 복사(Deep copy) (1) | 2021.10.19 |
[Java] Scanner() (0) | 2021.10.17 |
[Java] for문, 별찍기 (0) | 2021.10.12 |
[Java] 제어문 - 반복문(for 문) (0) | 2021.10.11 |