[JAVA] 배열
안녕하세요. 이번에는 배열에 대한 글입니다.
- 배열이란?
배열이란 동일한 자료형에 대한 묶음 형식의 참조 자료형이다. 불변형으로서 선언할 때 크기를 먼저 할당해야 하며 다시 크기를 변경할 수 없다는 점이 특징이다.
package classes;
public class Example {
int a = 10;
int b = 20;
int c = 30;
//....
int arr[] = {10, 20, 30};
}
기존 배열을 사용하지 않았을 때는 아무리 연관된 또는 같은 자료형의 값이어도 각 변수에는 하나의 값만 대입할 수 있기 때문에 여러 값을 저장할 때 일일이 변수를 선언해야 했다. 그러나 배열을 사용하면 코드의 길이가 간결해질 뿐만 아니라 하나의 배열 변수에 여러 개의 값을 저장할 수 있기 때문에 보다 가독성이 좋고 데이터 관리하기에 용이하다.
- 배열 선언 방법 및 원리
package classes;
public class Example {
int[] a; // int 형 배열
double k[]; // double 형 배열
}
다음과 같이 배열은 자료형[] 변수 뿐만 아니라 자료형 변수[] 형식으로도 선언 가능하다.
동일한 자료형으로만 묶을 수 있다는 특징이 존재하기 때문에 반드시 자료형을 명시해야 하며 이 안에는 해당되는 자료형에 맞는 값 외에는 어떠한 값도 들어갈 수 없다.
배열은 참조 자료형이므로 Stack에 변수를 선언하고 내부의 데이터 또는 값은 Heap메모리에 주소값을 참조하는 방식으로 저장된다. 하지만, 소스코드 처럼 int[] a는 단순히 선언만 했을 뿐, 내부에 값을 삽입하지 않았다. 그렇기 때문에 배열은 단순히 선언만 해서 Stack 메모리에 변수만 존재하고 참조할 수 있는 주소값은 존재하지 않는다.
지금까지 배열을 선언하는 방법을 배웠고, 이제는 생성하는 법에 대해 알아본다.
이때 생성하는 방법은 크게 2가지인데, new 키워드를 통해 길이를 지정하는 방식과 직접 값을 대입하는 방식이 있다.
package classes;
public class Example {
public static void main(String[] args) {
int[] a = new int[6];
String name[] = new String[10];
}
}
다음과 같이 new 연산자를 통해 배열의 크기를 선언할 수 있다. 배열을 생성할 때는 불변형인 만큼 길이를 반드시 지정해야 한다는 점을 확인할 수 있다. 이는 변수에 객체를 대입하는 방식이며 자료형[] 변수명 = new 자료형 [배열의 길이]; 형식을 통해 객체 생성과 변수 대입을 동시에 진행한다.
이를 좀 더 세분화하여 보면 각각의 의미는 다음과 같다. [ int a[] = new int[6]; ]
package classes;
public class Example {
public static void main(String[] args) {
int[] a = new int[6];
a[0] = 10;
a[1] = 20;
a[2] = 30;
}
}
다음과 같이 선언 및 생성해둔 배열에 값을 삽입하면 그림과 같이 Heap 메모리 영역에 데이터가 하나 둘 씩 저장되는 것을 확인할 수 있다. 이 때 저장하지 않은 부분은 참조 자료형 특성 상 객체가 위주이므로 0으로 자동 저장되어진다.
출력문을 사용해서 a[3]과 같이 따로 값을 저장하지 않은 부분을 출력해보면 0이라고 출력되는 것을 볼 수 있다.
package classes;
public class Example {
public static void main(String[] args) {
int[] a = new int[6];
a[0] = 10;
a[1] = 20;
a[2] = 30;
System.out.println(a[-1]);
// Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 6 at classes.Example.main(Example.java:11)
}
}
다음과 같이 배열의 값을 출력하려고 할 때 배열의 범위 밖을 설정할 경우 예외가 발생한다. 배열은 0부터 5까지 총 6개의 공간으로 구성되어 있는데 여기서는 -1을 출력하려고 했다. 범위 밖이다. 그래서 ArrayIndexOutOfBoundsException, 배열의 범위를 벗어났다는 예외 오류를 확인할 수 있다.
package classes;
public class Example {
public static void main(String[] args) {
int[] a = new int[] {10, 20, 30, 40, 50};
int[] b;
b = new int[] {20, 40, 60, 80, 100};
int[] a2 = {10, 30, 50, 70, 90};
/*
int[] b2;
b2 = {0, 20, 60, 80, 150};
*/
}
}
다음은 배열을 생성하는 또 다른 방식은 배열에 값을 직접적으로 삽입하는 방법이다.
소스코드와 같이 배열 변수에 new 연산자를 사용해서 별도로 저장 용량을 지정하지 않고 값부터 직접적으로 넣어서 간접적으로 배열의 용량을 지정한다. 배열 객체 생성과 함께 값도 대입할 수 있다는 점을 확인할 수 있다.
또 하나는 new 생성자를 통해 객체를 생성하지 않고 값부터 대입하는 방식이다. 이때 객체 생성없이 값을 삽입하는 방식은 선언과 대입을 분리할 수 없다.
package classes;
public class Example {
public static void main(String[] args) {
int[] a = new int[] {10, 20, 30, 40, 50};
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}
이제 반복문을 통해 배열의 값을 모두 출력해보자. 이때 하나의 배열 안에 여러 개의 값이 있다는 점을 확인해서 for문 같은 반복문을 사용해서 배열 내부의 값을 모두 출력해야 한다. 일부의 값만 보고 싶으면 출력문 안에 a[i]을 활용해서 출력하자.
소스코드와 같이 반복문을 사용해서 배열의 값을 모두 출력하면 10 20 30 40 50이 나오는 점을 확인할 수 있다.
이때 .length는 메서드로서 배열과 문자열의 길이를 구할 때 사용한다. 반환값은 int 자료형이다.
- 2차원 배열
2차원 배열은 가로 및 세로 방향 또는 행과 열을 사용한다는 점에서 1차원 배열과 차이점이 존재한다.
package classes;
public class Example {
public static void main(String[] args) {
int[][] a; // 자료형[][] 변수명
int b[][]; // 자료형 변수명[][]
int[] c[]; // 자료형[] 변수명[]
}
}
2차원 배열을 선언하는 방법은 다음과 같이 크게 3가지가 있다는 점을 확인할 수 있다.
2차원 배열은 행과 열로 구성되어 있는 배열이다. 행은 세로의 집합, 열은 가로의 집합인 점을 확인할 수 있다.
package classes;
public class Example {
public static void main(String[] args) {
int[][] a = new int[3][4];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[0][3] = 4;
a[1][0] = 5;
a[1][1] = 6;
a[1][2] = 7;
a[1][3] = 8;
//... 다음과 같이 행과 열의 위치값을 통해 데이터를 삽입한다.
System.out.println(a[0].length); // 열의 길이
System.out.println(a.length); // 행의 길이
int[][] c = new int[][] {
{10, 20, 30},
{40, 50, 60}
};
// 이중 for문으로 2차원 배열의 모든 값을 출력할 수 있다.
for (int i = 0; i < c.length; i++) {
for (int j = 0; j <c[0].length; j++) {
System.out.println(c[i][j]);
}
}
}
}
다음과 같이 2차원 배열은 행과 열을 통해 조금 더 입체적으로 다방면적으로 데이터를 저장할 수 있다는 점을 알 수 있다.
각 종류별로 데이터를 관리할 때 또는 용도 또는 목적별로 데이터를 관리해야 할 때 용이하다.
또한 2차원 배열에서 행과 열의 길이를 확인할 수 있다. 행은 a[0].length와 같이 배열의 열의 길이를 파악할 수 있으며 a.length는 배열의 행 길이를 파악할 수 있다. 그리고 이를 활용하여 이중 for문과 함께 2차원 배열의 모든 값을 출력할 수 있다는 점 또한 확인할 수 있다.
package classes;
public class Example {
public static void main(String[] args) {
int[][] a = new int[3][];
a[0] = new int[] {10, 20, 30};
a[1] = new int[] {40, 50};
a[2] = new int[] {60, 70, 80, 90, 100};
System.out.println(a[0].length); //3
System.out.println(a[1].length); //2
System.out.println(a[2].length); //5
}
}
다음 소스코드는 비정방 배열이다. 이때 비정방 배열은 각 행마다 열의 길이가 다른 2차원 배열을 의미한다. 그만큼 들쭉날쭉할 수도 있다는 점을 알 수 있다. 행의 길이만 선언해두면 나머지 열의 길이는 자율적으로 길이를 조정하면서 데이터를 저장할 수 있다. 그리고 .length 메서드를 통해 각 행의 길이를 확인할 수 있는데 이때 각 행마다 열의 길이가 다른 만큼 서로 다른 값을 출력하고 있다는 점도 확인할 수 있다.
여담으로 int[][] k = { {10, 20, 30}, {40, 50, 60, 70}, {80, 90}, {100} }; 과 같이 별도의 길이 지정을 거치지 않고 초깃값을 대입하는 방식으로 배열을 구성해도 된다.
다음 글은 String에 관한 메서드 추가 설명입니다.