배열
🤔 배열이란?
- 자료형이 같은 둘 이상의 데이터 값을 저장할 수 있는 메모리 공간을 의미합니다.
- 배열은 구조에 따라 1차원 배열과 2차원 이상의 배열인 다차원 배열로 구분됩니다.
- 먼저 1차원 배열부터 살펴보겠습니다.
❓ 1차원 배열이란?
- 자료형이 같은 둘 이상의 데이터를 저장할 수 있는 1차원 구조의 메모리 공간을 의미합니다.
- 자바는 배열을 인스턴스(객체)로 인식하고 사용합니다.
1차원 배열의 선언
방법1
int [] array = new int[5]; //크기가 5인 int형 1차원 배열의 생성문
- 위의 코드를 뜯어보면 등호를 기준으로 왼편에는 배열의 참조 변수 선언과 오른쪽에는 배열의 생성을 나타납니다.
왼쪽(배열의 참조 변수 선언)
int[] array //배열의 인스턴스를 참조할 수 있는 '참조변수의 선언'
오른쪽(배열의 생성)
new int[5] //int형 값 5개를 저장할 수 있는 '배열 인스턴스(객체)의 선언'
- 또한 다음과 같이 배열의 참조 변수 선언과 배열의 생성을 따로 구분하여 1차원 배열을 선언할 수 있습니다.
방법2
int [] array;//배열의 참조변수 선언
array = new int[5]; //배열의 인스턴스 생성
- 아래의 코드를 통해 배열을 더욱 자세히 살펴봅시다.
💻 예시 코드
public class ArrayIsInstance{
public static void main(String[] args) {
//길이가 5인 int형 1차원 배열 생성
int[] array1 = new int[5];
//길이가 7인 double형 1차원 배열 생성
double[] array2 = new double[7];
//배열의 참조변수와 인스턴스 생성을 분리하여 선언한 float형 1차원 배열의 생성
float[] array3;
array3 = new float[9];
//배열의 인스턴스 변수에 접근하여 출력
System.out.println("배열 ar1 길이:" + array1.length);
System.out.println("배열 ar2 길이:" + array2.length);
System.out.println("배열 ar3 길이:" + array3.length);
}
}
📸 출력 결과
배열 array1 길이:5
배열 array2 길이:7
배열 array3 길이:9
- 위의 코드에서 배열의 인스턴스 변수의 length에 접근하여 생성된 배열의 길이를 출력하였습니다.
- 이렇게 인스턴스 변수를 통해 접근이 가능하다는 것은 배열이 인스턴스(객체)임을 알려줍니다.
- 또한 1차원 배열의 참조변수(인스턴스 변수)는 배열의 길이에 상관없이 참조가 가능합니다.
public static void main(String[] args){
int[] array = new int[50];
System.out.println("length: " + array.length); //length:50
array = new int[100]; //길이가 다른 배열을 참조함
System.out.println("length: " + array.legnth); //length: 100
}
- 배열은 int형 doulbe형과 같은 기본 자료형을 대상뿐만 아니라 다른 인스턴스(객체)를 저장할 수 있는 배열의 생성도 가능합니다.
💻 예시 코드
class Box{ //Box 인스턴스(객체) 정의
private String conts;
public Box(String conts) {
this.conts = conts;
}
public String toString(){
return conts;
}
}
public class ArrayInInstance2 {
public static void main(String[]args){
Box[] array = new Box[5]; // 길이가 5인 Box형 1차원 배열의 생성
System.out.println("length : " + array.length);
}
}
📸 출력 결과
length : 5
- 위의 코드에서 Box 클래스를 정의하고 이 클래스의 인스턴스 5개를 정의할 수 있는 배열을 생성하였습니다.
Box[] array = new Box[5];
- 여기서 주의해야 할 사항은 다음과 같습니다.
-> Box 인스턴스 5개를 저장할 수 있는 참조변수의 배열 생성입니다.
- 즉, Box 인스턴스(객체) 생성과는 관계가 없습니다.
- 단지 5개의 Box 인스턴스를 저장할 수 있는 배열을 만든다는 점입니다.
배열에 값을 저장하고 참조하는 방법
- 다음으로는 배열에 값을 저장하고 이를 참조하는 방법에 대해서 알아봅시다.
int [] array = new int[3];//int형 값 3개를 저장할 수 있는 배열을 선언
생성된 배열에 값을 저장하는 방법
- 생성된 배열의 첫번째 공간(첫번째 요소)에 값을 저장하는 방법은 다음과 같습니다.
array[0] = 10;
배열의 요소
- 다음으로 두번째 요소, 세번째 요소를 값을 저장하면 다음과 같습니다.
array[1]= 9; //배열의 두번째 요소에 정수 9을 저장
array[2]= 8; //배열의 세번째 요소에 정수 8을 저장
생성된 배열의 값을 참조하는 방법
- 생성된 배열의 값을 참조하는 방법은 다음과 같습니다.
- 다음은 배열 array에 저장된 모든 요소의 값을 저장하는 코드입니다.
int num = array[1] + array[2] + array[3];
- 앞서 살펴봤던 Box형 배열에 인스턴스의 값을 저장하고 참조하는 방법도 위와 동일합니다.
- 앞서 봤던 Box형 배열의 코드를 이용해 값을 저장하고 참조하는 방법을 살펴봅시다.
💻 예시 코드
class Box{
private String conts;
Box(String cont){
this.conts = cont;
}
public String toString(){
return conts;
}
}
public class BoxArray {
public static void main(String[]args){
Box[] array = new Box[3];
//Box 배열에 인스턴스의 값을 저장
array[0] = new Box("First");
array[1] = new Box("Second");
array[2] = new Box("Third");
//저장된 인스턴스의 참조
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
}
}
📸 출력 결과
First
Second
Third
- 위의 코드를 살펴보면 Box형 배열의 생성 이후에 다음과 같이 인스턴스를 생성하고 값을 저장했습니다.
array[0] = new Box("First");
array[1] = new Box("Second");
array[2] = new Box("Third");
- 그리고 저장된 Box형 배열의 인스턴스에 있는 값들은 다음과 같이 참조합니다.
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
- 이와 관련하여 한가지 코드를 더 살펴봅시다. String형 배열에 문자열을 저장하고 참조하는 코드입니다.
public class StringArray {
public static void main(String[]args){
String[] sr = new String[7];
sr[0] = new String("Java");
sr[1] = new String("System");
sr[2] = new String("Compiler");
sr[3] = new String("Park");
sr[4] = new String("Tree");
sr[5] = new String("Dinner");
sr[6] = new String("Brunch Cafe");
int cnum = 0;
for(int i = 0; i< sr.length; i++)
cnum += sr[i].length();
System.out.println("총 문자의 수: " + cnum);
}
}
출력 결과
총 문자의 수: 43
위의 코드를 통해 주의 깊게 살펴보야 할 코드는 다음과 같습니다.
for(int i = 0; i < sr.length;i++)
cnum += sr[i].length(); //String 인스턴스의 length 메소드 순차적 호출!
- 반복문에서 변수i를 이용하여 모든 배열의 요소에 접근하였습니다.
- 이렇게 반복문을 이용하면 ‘배열의 순차적 접근’을 진행할 수 있는 문장를 구성할 수 있습니다.
- 단 두줄의 코드만을 이용해서 모든 문자열에 접근하는 배열이 아니면 불가능합니다.
배열을 생성과 동시에 초기화하기
배열도 변수와 마찬가지로 생성과 동시에 초기화가 가능합니다.
올바른 예 1)
int[] array = new int[] {1,2,3}; //배열의 생성과 동시에 초기화
- 초기화할 값들의 수를 배열의 길이 정보를 계산할 수 있으므로 배열의 길이 정보를 생략하도록 약속하였습니다.
올바른 예 2)
int [] arr = {1,2,3);
- 위와 같이 문장을 줄여서 표현할 수도 잇습니다.
잘못된 예
int[] array3 = new int[3] {1,2,3}; //컴파일 오류가 발생함
배열의 참조 변수 선언
이번에는 배열의 참조 변수 선언에 대해 알아봅시다.
배열의 참조 변수 선언에는 다음과 같이 두 가지 방법이 있습니다.
참조 변수 선언 1)
int [] arr = new int[3]; //좀 더 자주 사용되는 방법
참조 변수 선언 2)
int arr[] = new int[3];
배열의 참조 값과 메소드
배열도 인스턴스(객체)이므로 메소드를 호출할 때 참조 값을 전달하는 것이 가능합니다.
이와 관련하여 다음의 코드를 살펴봅시다.
public static void main(String[] args) {
int [] ar = {1,2,3,4,5,6,7};
int sum = sumOfAry(ar); //배열의 참조 값 전달
....
}
위에서 호출한 메소드에 대해서도 살펴봅시다.
- 호출된 메소드의 배개변수는 배열의 참조변수가 되어야 합니다.
static int sumOfAry(int[] ar) {
int sum = 0;
for(int i = 0;i<ar.length;i++){
sum += ar[i];
return sum;
}
또한 다음과 같이 배열의 참조값을 반환하는 메소드를 정의하는 것도 가능합니다.
static int[] makeNewIntAry(int len){
int[] ar = new int[len];
return ar;
}
🔥 배열도 인스턴스임으로 우리가 사용하던 인스턴스의 참조 값을 전달하고 반환했듯이
배열의 참조 값도 전달 및 반환하는 방법또한 동일합니다.
배열의 초기화 및 복사
배열은 생성되면 모든 요소의 값이 0 또는 null로 초기화 됩니다.
예시1)
- 다음과 같이 처음에 배열이 생성되면 그 안의 요소들은 0으로 초기화됩니다.
int [] array = new int[10]; //생성된 배열의 모든 요소 0으로 초기화된다.
예시2)
- 다음과 같이 인스턴스(객체)의 배열을 생성하면 모든 요소들은 null로 초기화 됩니다.
String[] array = new String[10];//생성된 배열의 모든 요소는 null로 초기화된다.
그런데 int형 배열 등 기본 자료형의 배열을 생성할 때 0이외의 값을 초기화해야 할 경우가 있습니다.
이럴 경우에는 반복문을 이용해서 원하는 값을 배열에 저장할 수도 있지만
다음과 같이 메소드를 호출해서 원하는 값을 배열에 저장할 수도 있습니다.
public static void fill(int[]a, int val); //val로 전달되는 값으로 배열 a를 초기화한다.
public static void fill(int []a, int fromIndex, int toIndex,int val); //인덱서 fromIndex에서 부터 toIndex -1까지 val의 값으로 배열 a를 초기화한다.
- 위의 두 메소드는 java.util.Arrays 클래스에 정의되어 있으며 각 기본 자료형마다 별도의 메소드가 오버로딩되어 있습니다.
또한 배열을 복사해야 하는 상황도 종종 생기는데 이때에도 반복문을 구성해서 복사를 진행할 수도 있지만
java.lang.System 클래스의 메소드를 통해서 복사할 수 있습니다.
public static void arraycopy(Object src, int srcPos,Object dest, int destPos, int length)
-> 복사 원본의 위치: arc의 인덱스 scrPos
-> 복사 대상의 위치: 배열 dest의 인덱스 destPos
-> 복사할 요소의 수: length
지금까지 알아본 메소드들에 대해서 코드를 통해 자세히 살펴봅시다.
import java.util.Arrays;
public class ArrayUtils {
public static void main(String[]args){
int[] ar1 = new int[10];
int[] ar2 = new int[10];
//배열 ar1의 요소 값을 7로 설정함
Arrays.fill(ar1,7);
//배열 ar의 요소 0의 값을 배열 ar2의 요소 3번째부터 4개까지(6번째까지)복사함
System.arraycopy(ar1,0,ar2,3,4);
for(int i = 0; i< ar1.length;i++){
System.out.print(ar1[i] + " ");
}
System.out.println();
for(int i = 0; i< ar2.length;i++){
System.out.print(ar2[i] + " ");
}
}
}
출력 결과
7 7 7 7 7 7 7 7 7 7
0 0 0 7 7 7 7 0 0 0
enhanced for문
- enhanced for문은 자바 5버전에서 추가되었습니다.
- 그리고 지금까지 많이 사용되는 반복문 중 하나입니다.
❓ enhanced for문이란?
🔥 배열에 저장된 모든 요소의 값 중에서 연산을 하거나 특정 조건에 따른 값 등을 찾을 때 사용하는 편리한 반복분이다.
이해하기 위해 그동안 사용한 for문과 enhanced for문에 대해 비교해 보겠습니다.
배열의 저장된 모든 값을 출력하는 요구조건에 따른 for 반복문과 enhanced for문에 대해서 비교하겠습니다.
for문의 경우
int[] array = {1,2,3,4,5};
for(int i = 0;i<array.length;i++){
System.out.println(array[i]);
}
enhanced for문의 경우
for(int e: array) {
System.out.println(e);
}
enhanced for문은 기존 for문에 비해서 다음과 같은 두가지 장점이 있습니다.
💡 1. 코드의 양이 줄어든다.
2. 반복문의 구성 과정에서 배열의 길이를 직접 확인하고 입력할 필요가 없다.
enhanced for문의 구성
enhanced for는 다음과 같이 구성되어 있습니다.
for(요소 : 배열){
반복할 문장들
}
- 배열에서는 반복의 대상인 배열의 참조변수가 오게 됩니다.
- 요소부분에서는 배열의 요소가 하나씩 담기게 됩니다.
enhanced for문의 과정
다음과 같이 배열 array가 있고 배열의 모든 요소들을 enhance for문으로 출력한다고 가정하겠습니다.
int [] array = {1,2,3,4,5};
for(int e : array) {
System.out.println(e);
}
첫번째 반복의 상항
- 첫번째의 요소가 변수 e에 담겨 문장을 실행합니다.
//첫 번째 반복의 상황
for(int e: array{
e = array[0];
System.out.println(e);
}
두번째 반복의 상황
- 배열 array의 두 번째 요소가 변수 e에 담겨 실행됩니다.
//두 번째 반복의 상황
for(int e: array) {
e = array[1];
System.out.println(e);
}
이렇게 배열 array의 요소들이 마지막까지 변수 e에 담겨서 출력됩니다.
인스턴스(객체) 배열을 대상으로 하는 enhanced for문
다음과 같이 배열에 저장된 내용이 ‘인스턴스의 참조 값’인 경우에도 enhanced for문을 활용할 수 있습니다.
- 먼저 Box라는 클래스를 정의했다고 가정하겠습니다.
다음의 코드를 살펴보겠습니다.
Box[] ar = new Box[10];
for(Box e : ar){
~~~
}
enhanced for문의 과정
첫번째 반복의 상황
// 첫 번째 반복의 상황
for(Box e : array) {
e = array[0]; //첫 번째 요소에 저장된 참조 값을 e에 대입
~~
}
두번째 반복의 상황
// 두 번째 반복의 상황
for(Box e : array) {
e = array[1]; //두 번째 요소에 저장된 참조 값을 e에 대입
~~
}
이와 관련하여 다음의 코드를 통해 자세히 살펴보겠습니다.
- 상자에 부여된 번호를 확인하고 enhanced for문을 통해 번호 505번의 박스를 찾아 내용물을 출력하는 코드입니다.
class Box2{
private String contents;
private int boxNum;
public Box2(int boxNum, String contents) {
this.contents = contents;
this.boxNum = boxNum;
}
public int getBoxNum(){
return boxNum;
}
public String toString(){
return contents;
}
}
public class EnhancedForInst {
public static void main(String[]args){
Box2[] ar = new Box2[5];
ar[0] = new Box2(101,"Coffee");
ar[1] = new Box2(202,"Computer");
ar[2] = new Box2(303,"Apple");
ar[3] = new Box2(404,"Dress");
ar[4] = new Box2(505,"Fairy-tale book");
// 배열에서 번호가 505인 Box를 찾아 그 내용물을 출력하는 반복문
for(Box2 e: ar){
if(e.getBoxNum() == 505)
System.out.println(e);
}
}
}
출력 결과
Fairy-tale book
이렇게 배열에 ‘인스턴스 참조 값’을 대상으로 한 배열에도 enhanced for문을 사용할 수 있습니다.
다차원 배열
❓ 다차원 배열이란?
🔥 배열의 구조가 2차원 이상의 형태를 보이는 배열을 가리켜 다차원 배열이라고 합니다.
2차원 배열의 생성과 접근
- 1차원 배열은 둘 이상의 변수가 ‘선의 형태’로 존재하는 배열입니다.
- 반면 2차원 배열은 다수의 변수가 ‘면의 형태’로 존재하는 배열입니다.
보다 쉬운 이해를 위해 아래의 그림을 살펴봅시다.
1차원 배열
2차원 배열
2차원 배열의 생성
int[][] array = new int [3][4]; //세로의 길이가 3, 가로의 길이가 4인 2차원 배열의 생성
- int[ ] [ ]은 2차원 배열의 참조변수 형을 의미합니다.
- new int[3][4]에서 2차원 배열의 세로 길이는 3을, 가로 길이는 4임을 의미합니다.
2차원 배열의 생성의 코드를 몇 개 더 살펴봅시다.
int[][] array1 = new int [7][2]; //세로의 길이가 7, 가로의 길이가 2인 int형 2차원 배열의 생성
double[][] array2 = new double[3][5]; //세로의 길이가 3, 가로의 길이가 5인 double형 2차원 배열의 생성
String[][] array3 = new String[3][7]//세로의 길이가 3, 가로의 길이가 7인 String형 2차원 배열의 생성
다음의 코드를 통해 2차원 배열을 살펴봅시다.
public class TwoDimenArray {
public static void main(String[]args){
int[][] arr = new int[3][4];//세로의 길이가 3, 가로의 길이가 4인 2차원 배열의 생성
int num = 1;
//배열에 값을 저장
for(int i = 0; i<3; i++){
for(int j = 0; j<4; j++){
arr[i][j] = num;
num++;
}
}
//배열에 저장된 값을 출력
for(int i = 0; i<3; i++){
for(int j = 0;j <4; j ++){
System.out.print(arr[i][j] + "\\t");
}
System.out.println();
}
}
}
출력 결과
1 2 3 4
5 6 7 8
9 10 11 12
2차원 배열의 구조
- 이번에는 2차원 배열의 구조를 좀 더 자세하게 뜯어봅시다.
아래의 코드를 통해 2차원 배열을 살펴봅시다.
public class TwoDimenArray2 {
public static void main(String[]args){
int[][] arr = new int[3][4]; //세로가 3, 가로가 4인 2차원 배열의 생성
int num = 1;
for(int i = 0; i< arr.length; i++) {
for (int j = 0; j < arr[i].length;j++){
arr[i][j] = num;
num++;
}
}
for(int i = 0; i< arr.length;i++){
for(int j = 0;j<arr[i].length;j++){
System.out.print(arr[i][j] + "\\t");
}
System.out.println();
}
}
}
출력 결과
1 2 3 4
5 6 7 8
9 10 11 12
분석
위의 코드를 뜯어서 분석해 봅시다.
- 위의 코드에서 2차원 배열을 생성하였습니다.
int[][] arr = new int[3][4];
- 이때 참조 변수 arr의 실제 형태는 다음과 같습니다.
(세로로 되어 있으나 1차원 배열의 형태를 띄고 있습니다.)
- 배열의 요소는 arr[0],arr[1],arr[2]이고 이 셋 모두 다 참조 변수입니다.
(그러나 그냥 참조 변수가 아닌 ‘1차원 배열을 참조하는 참조변수’입니다) - 이들 참조 변수는 각각 길이가 4인 1차원 배열을 다음과 같이 참조합니다.
- 따라서 arr[0].length, arr[1].length,arr[2].lengtyh로 각 참조변수가 참조하는 배열의 길이를 확인할 수 있습니다.
정리
🔥 2차원 배열은 다수의 1차원 배열들이 묶여서 만들어집니다.
위와 같은 구조를 알고 잇음으로 보다 다양한 코드를 사용할 수 있습니다.
public static void main(String[] args){
int[][] arr = new int[3][4]; //세로의 길이가 3,가로의 길이가 4인 int형 2차원 배열을 생성
....
arr[1] = new int [7]; //두번째 줄의 배열을 교체
}
따라서 2차원 배열은 다음과 같은 모습으로 변경됩니다.
2차원 배열의 초기화
2차원 배열도 1차원 배열처럼 초기화가 가능합니다.
방법1
int[][] arr = new int[][]{
{11,22,33}, //1행 초기화
{44,55,66}, //2행 초기화
{77,88,99} //3행 초기화
};
방법2
int[][] arr = {
{11,22,33}, //1행 초기화
{44,55,66}, //2행 초기화
{77,88,99} //3행 초기화
};
❓ 그럼 다음과 같이 2차원 배열을 초기화하면 어떤 배열이 만들어질까요?
int[][] arr = {
{11},
{22,33},
{44,55,66}
};
코드를 통해 살펴봅시다.
public class PartiallyFilledArray {
public static void main(String[]args){
int[][] arr = {
{11},{22,33},{44,55,66}
};
//배열의 구조대로 내용 출력
for(int i = 0; i<arr.length;i++){
for(int j = 0;j<arr[i].length;j++){
System.out.print(arr[i][j] + "\\t");
}
System.out.println();
}
}
}
출력 결과
11
22 33
44 55 66
정리
🔥 “초기화 하는 값의 수”에 따른 길이의 배열이 생성됩니다.
- 2차원 배열의 가로 길이가 행 별로 다른 2차원 배열이 생성됩니다.
- 따라서 초기화할 때는 잘못하여 원치 않는 길이의 배열이 만들어지지 않도록 주의해야 합니다.
📒 Reference (참고 자료)
- 윤성우의 열혈 자바
'프로그래밍 언어 > Java문법 - 객체지향' 카테고리의 다른 글
11. Java 객체지향 문법(11) - 상속과 오버라이딩 (0) | 2022.11.02 |
---|---|
10. Java 객체지향 문법(10) - 상속의 기본 (0) | 2022.11.02 |
8. Java 객체지향 문법(8) - 콘솔 입력과 출력 (0) | 2022.10.28 |
7. Java 객체지향 문법(7) - String 클래스 (0) | 2022.10.28 |
6. Java 객체지향 문법(6) - 메소드 오버로딩 (0) | 2022.10.28 |