배열

gustjtmd·2022년 1월 27일
0

Java

목록 보기
8/40

1차원 배열의 이해와 활용

배열은 '자료형이 같은 둘 이상의 값'을 저장할 수 있는 메모리 공간을 의미한다 그리고 배열은 그 구조에 따라서 '1차원 배열'과 2차원 이상의 '다차원 배열'로 나뉜다.

1차원 배열의 생성 방법

1차원 배열은 다음과 같이 정의 할 수 있다
"타입이 같은 둘 이상의 데이터를 저장할 수 있는 1차원 구조의 메모리 공간"

자바는 배열도 인스턴스로 처리한다 즉 '자바에서는 배열도 인스턴스'이다.

int[] ref = new int[5];	//길이가 5인 int형 1차원 배열의 생성문

int[] ref
	-> int1차원 배열 인스턴스를 참조할 수 있는 '참조변수의 선언'
    
new int[5];
	-> int형 값 5개를 저장할 수 있는 '배열 인스턴스의 생성'
    
이와 관련된 코드

public class ArraysIsInstance {
    public static void main(String[] args) {
        //길이가 5인 int형 1차원 배열의 생성
        int[] ar1 = new int[5];

        //길이가 7인 double형 1차원 배열의 생성
        double[] ar2 = new double[7];

        //배열의 참조변수와 인스턴스 생성 분리
        float[] ar3;
        ar3 = new float[9];

        //배열의 인스턴스 변수 접근
        System.out.println("배열 ar1 길이 : " +ar1.length);
        System.out.println("배열 ar2 길이 : " + ar2.length);
        System.out.println("배열 ar3 길이 : " + ar3.length);
    }
}


배열 ar1 길이 : 5
배열 ar2 길이 : 7
배열 ar3 길이 : 9

---------------------------------------------------------------------

위 코드에서 배열의 인스턴스 변수 length에 접근하여 배열의 길이 정보를 출력하였다.
이렇게 인스턴스 변수에 접근이 가능하다는 것은 배열이 인스턴스임을 보이는 결과이기도 하다
배열은 다음과 같이 1차원 배열의 참조변수는 배열의 길이에 상관없이 참조가 가능하다

int[] ar = new int[50];
System.out.println(ar.length);	//length : 50
ar = new int[100]	//길이가 다른 배열 참조
System.out.pirntln(ar.length);	//length 100
배열은 int, double과 같은 기본 자료형을 대상으로만 생성할 수 있는것이 아니다
인스턴스를 저장할 수 있는 배열의 생성도 가능하다.

class Box{
    private String conts;

    Box(String cont){
        this.conts = cont;
    }
    public String toString(){
        return conts;
    }
}
public class ArrayIsInstance2 {
    public static void main(String[] args) {
        Box[] ar = new Box[5];  //길이가 5인 Box형 1차원 배열의 생성
        System.out.println("length : "+ar.length);  //length: 5
    }
}

length : 5

------------------------------------------------------------------------
위 코드에서는 Box 클래스를 정의하고 이 클래스의 인스턴스 5개를 저장할 수 있는 배열을
다음과 같이 생성하였다.

Box[] ar = new Box[5];

여기서 주의할 사실이 있는데 "이는 Box 인스턴스 5개를 저장할 수 있는 참조변수의 배열이다."

즉 이는 Box 인스턴스의 생성과는 관계가 없다 위의 문장을 통해 5개의 인스턴스를 저장할수 있는
배열이 생성될뿐.

배열을 대상으로 한 값의 저장과 참조

코드로 바로 확인해보자

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[] ar = new Box[3];

        //배열에 인스턴스 저장
        ar[0] = new Box("First");
        ar[1] = new Box("Second");
        ar[2] = new Box("Third");

        //저장된 인스턴스의 참조
        System.out.println(ar[0]);
        System.out.println(ar[1]);
        System.out.println(ar[2]);
    }
}

First
Second
Third

------------------------------------------------------------------------
위 코드에서 배열 생성 이후에 다음과 같이 인스턴스를 생성하여 저장하였다.

        ar[0] = new Box("First");
        ar[1] = new Box("Second");
        ar[2] = new Box("Third");
이와 같이 인스턴스를 생성하고 저장했을때의 배열과 인스턴스의 관계는 다음과 같다

그리고 배열에 저장된 인스턴스는 다음과 같이 참조한다.

	System.out.println(ar[0]);
        System.out.println(ar[1]);
        System.out.println(ar[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("Complier");
        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

-------------------------------------------------------------------

반복문을 이용하면 '배열의 순차적 접근'을 진행하는 문장을 구성할 수 있다.
그리고 이것이 배열이 갖는 대표적인 장점 중 하나이다. 
참조변수 일곱개를 선언하여 입곱개의 문자열을 저장할 수는 있다.
그러나 단 두줄의 코드만을 이용해서 모든 문자열에 접근하는 것은 배열이 아니면 불가능하다.

배열을 생성과 동시에 초기화하기

배열도 변수와 마찬가지로 생성과 동시에 초기화가 가능하다

int[] arr = new int[3];

이 배열을 생성과 동시에 초기화 하려면 초기화 값들을 다음과 같이 중괄호를 이용해서 나열하면 됨

int arr = new int[] {1,2,3};

다음과 같이 줄여서도 가능하다
int[] arr = {1,2,3};

다음과 같이 하면 초기화할 값들의 수를 통해 배열의 길이 정보를 계산할 수 있으므로 컴파일 오류

int arr = new int[3] {1,2,3};	//컴파일 오류

배열의 참조 값과 메소드

배열도 인스턴스이므로 메소드 호출시 참조 값의 전달이 가능하다 코드로 확인해보자

public class ArrayTest {

    static int sumOfAry(int[] arr){
        int sum = 0;
        for(int i = 0; i<arr.length; i++)
            sum += arr[i];
        return sum;
    }

    static int[] makeNewIntAry(int len){
        int[] ar = new int[len];
        return ar;
    }

    public static void main(String[] args) {
        int[] ar = {1,2,3,4,5,6,7};
        int sum = sumOfAry(ar);
        System.out.println("1부터 7까지의 합 : "+ sum);

        int[] arr = makeNewIntAry(100);
        System.out.println("arr의 길이 : "+ arr.length);
    }

}


1부터 7까지의 합 : 28
arr의 길이 : 100

--------------------------------------------------------------------
결론적으로 배열도 인스턴스이다 따라서 인스턴스의 참조 값을 전달 및 반환하듯이
배열의 참조 값도 전달 및 반환할 수 있으며 그 방법에서도 차이가 없다.

배열의 초기화와 배열의 복사

배열이 생성되면 모든 요소는 0 또는 null로 초기화 된다

int[] ar = new int[10];	//배열의 모든 요소 0으로 초기화
String[] ar = new String[10];	//배열의 모든 요소 null로 초기화

그런데 ing형 배열과 같은 기본 자료형 배열을 0 이외의 값으로 초기화해야 할 때가 있다
이러한 경우 다음의 메소드 호출을 통해서 원하는 값을 배열에 저장할수 있다.

public static void fill(int[] a, int val)
-> 두번째 인자로 전달된 값으로 배열 초기화
public static void fill(int[] a, int fromIndex, int toIndex, int val)
-> 인덱스 fromIndex ~ toIndex(-1)범위까지 val의 값으로 초기화

위의 두 메소드는 java.util.Arrays 클래스에 정의되어 있으며 각 기본 자료형 별로 메소드가
오버로딩 되어있다. 

그리고 배열을 복사해야 하는 상황도 있는데 다음 jaa.lang.System 클래스의 메소드를 통해
가능하다.

public static void arraycopy(Object src, int srcPos, 
				Object dest, int destPos, int length)
-> 복사 원본의 위치 : 배열 src의 인덱스 srcPos
-> 복사 대상의 위치 : 배열 dest의 인덱스 destPos
-> 복사할 요소의 수 : length

코드로 확인해보자

public class ArrayUtils {
    public static void main(String[] args) {
        int[] ar1 = new int[10];
        int[] ar2 = new int[10];

        Arrays.fill(ar1, 7);    //배열 ar1을 7로 초기화
        System.arraycopy(ar1, 0, ar2, 3, 4);
        //배열 ar1을 ar2로 부분 복사

        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 

for - each문

for-each문은 자바 5에서 추가되었다. 지금은 많이 사용되는 반복문중 하나가 되었다.

for-each문의 이해와 활용

int[] ar = {1,2,3,4,5};
for(int i = 0; i < ar.length; i++){
	System.out.println(ar[i]);
}

for-each문의 구성을 배열을 기준으로 보면 다음과 같다

for(요소 : 배열){
	반복할 문장들
}

위 코드를 for-each문으로 구성하면

for(int e : ar)
	System.out.println(e);
}

for-each문에는 두가지 장점이 있다

1.   '코드의 양이 절대적으로 줄어든다'
2.   '반복문 구성 과정에서 배열의 길이 정보를 직접 확인하고 입력할 필요가 없다'



위의 반복문은 배열 ar을 대상으로 반복을 진행한다 따라서 첫번째 실행의 상황에서 변수 e에는
배열 ar의 첫번째 요소의 값이 담겨 '반복할 문장들'이 실행된다 다음과 같이 이해 가능


//첫번째 반복상황
for(int e : ar)
	e = ar[0];	//첫번째 요소가 변수 e에 담겨 아래 문장을 실행
	System.out.println(e);
}

//두번째 반복의 상황

for(int e : ar)
	e = ar[1];	//두번째 요소가 변수 e에 담겨 아래 문장을 실행
	System.out.println(e);
}
코드를 통해 확인해보자

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

        //배열 요소 전체 출력
        for(int e : ar){
            System.out.print(e + " ");
        }
        System.out.println();

        int sum = 0;

        //배열 요소 전체 합 출력
        for(int e : ar){
            sum += e;
        }
        System.out.print("sum : " +sum);
    }
}

1 2 3 4 5 
sum : 15

인스턴스 배열을 대상으로 하는 enhanced for문

배열에 저장된 내용이 '기본 자료형의 값'이 아닌 '인스턴스의 참조 값'인 경우에도
for-each문의 활용에 있어서 달라지는건 없다. 코드를 통해 확인해보자

class Box{
    private String contents;
    private int boxNum;

    Box(int num, String cont){
        boxNum = num;
        contents = cont;
    }
    public int getBoxNum(){
        return boxNum;
    }
    public String toString(){
        return contents;
    }
}
public class EnhancedForInst {
    public static void main(String[] args) {
        Box[] ar = new Box[5];
        ar[0] = new Box(101,"Coffee");
        ar[1] = new Box(202,"Computer");
        ar[2] = new Box(303,"Apple");
        ar[3] = new Box(404,"Dress");
        ar[4] = new Box(505,"Fairy-table book");

        //배열에서 번호가 505인 Box를 찾아 그 내용물을 출력하는 반복문
        for(Box e : ar){
            if(e.getBoxNum() == 505)
                System.out.print(e);
        }
    }

}


Fairy-table book

다차원 배열의 이해와 활용

배열의 논리적 메모리 구조가 2차원 이상의 형태를 보이는 배열을 가리켜 '다차원 배열'이라 한다 즉 2차원 배열도 다차원 배열이고 3차원 배열도 다차원 배열이다 그러나 일반적인 프로그램에서는 2차원 배열을 초과하는 구조의 배열을 잘 사용하지 않는다

2차원 배열의 생성과 접근

1차원 배열은 그 이름이 의미하듯이 둘 이상의 변수가 '선의 형태'로 존재하는 배열이다
반면 2차원 배열은 다수가 변수가 '면의 형태'로 존재하는 배열이다.

위 그림에서 보이듯이 세로 길이와 가로 길이가 각각 34int2차원 배열은 다음과 같이
생성한다

int[][] arr = new int[3][4];
-> 세로 길이가3, 가로 길이가 4int2차원 배열의 생성

int[][]int2차원 배열의 참조변수 형을 으미하고 new int[3][4]에서 3은 배열의
세로 길이를, 4는 가로 길이를 의미한다 

int[][] arr1 = new int[7][2];
-> 세로 길이가 7, 가로 길이가 2int2차원 배열의 생성

double[][] arr2 = new double[3][5];
-> 세로 길이가 3, 가로 길이가 5double2차원 배열의 생성

String[][] arr3 = new String[3][7];
-> 세로 길이가 3, 가로 길이가 7String2차원 배열의 생성

그리고 2차원 배열의 요소에 접근할 때에는 세로와 가로의 위치를 각각 지정해야 하는데
1차원 배열과 마찬가지로 위치 지정의 인덱스 값은 0에서부터 시작한다

arr[1][0] = 5;
-> 세로, 가로의 인덱스 위치가 각각 1,0인 요소에 5를 저장

arr[0][1] = 7;
-> 세로, 가로의 인덱스 위치가 각각 0,1인 요소에 7을 저장

코드로 확인해보자

public class TwoDimenArray {
    public static void main(String[] args) {
        int[][] arr = new int[3][4];
        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차원 배열의 구조

코드로 바로 확인해보자

public class TwoDimenArray2 {
    public static void main(String[] args) {
        int[][] arr = new int[3][4];
        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[0], arr[1], arr[2]이고 이 셋 역시 참조변수이다.
그냥 참조변수가 아닌 '1차원 배열을 참조하는 참조변수'이다 그래서 각각 길이가
41차원 배열을 참조한다.

따라서 arr[0].length, arr[1].length, arr[2].length로 각 참조변수가
참조하는 배열의 길이를 확인할 수 있다

코드를 작성할때에는 2차원 배열을 위의 구조로 생각하는 것이 좋다.
그러나 위의 구조를 알고 있음으로써 보다 다양한 코드를 이해할 수 있다.

int[][] arr = new int[3][4];
arr[1] = new int[7];	//두번째 줄의 배열을 교체하는 문장

위 코드로 2차원 배열의 두번째 줄을 길이가 7인 배열로 교체하였다.
따라서 2차원 배열이 다음의 모습으로 바뀌게 된다.

2차원 배열의 초기화

1차원 배열과 마찬가지로 2차원 배열도 다음과 같이 생성과 동시에 초기화가 가능하다.

int[][] arr = {
	{11,22,33},	//1행 초기화
    	{44,55,66},	//2행 초기화
    	{77,88,99}	//3행 초기화
};

만약 다음과 같이 초기화를 하면 어떠한 배열이 만들어질까?
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차원 배열이 생성된다. 
profile
반갑습니다

0개의 댓글