티스토리 뷰

JAVA/JAVA Theory

[JAVA] 12. Array(배열)

쟌쥰 2019. 11. 16. 20:28

Array : 같은 타입의 변수 여러개를 묶어서 사용. 처음 생성 시 크기가 정해진다.

같은 자료형의 변수 여러 개를 하나의 묶음으로 만들어 하나의 이름으로 다루는 것을 배열이라고 한다. 데이터를 저장하기 위해 여러 개의 변수를 선언할 수도 있지만 관리해야 하는 변수가 많아지면 코드가 매우 복잡하고 많아지게 된다. 이러한 경우 하나의 배열이름으로 여러 개의 변수들을 다룰 수 있으면 코드를 간단하게 처리할 수 있게 된다.

자바에서는 배열 공간은 자유 메모리 영역인 Heap 영역에 할당하도록 지정되어 있으며, 배열변수는 할당된 배열공간의 주소를 저장하며, 배열공간의 주소를 이용해 인덱스(순번, index)를 참조하는 방식으로 값들을 처리하도록 정해두었다. 

 

1. Array 의 선언과 생성

배열의 선언 : 배열공간의 주소 저장용 참조 변수를 만드는 것

타입[] 변수이름;
타입 변수이름[];

배열을 선언하면 참조형 변수가 생성된다. 배열을 선언한다 해서 값을 저장하는 공간이 생기지는 않는다.

 

배열의 생성 : Heap영역에 값을 저장하는 변수들을 연속 나열 할당하고, 발생한 배열 공간의 시작주소를 선언된 배열 레퍼런스에 대입한다.

배열참조변수 = new 데이터타입[연속 할당될 변수 갯수];

배열을 생성할 때 배열의 길이(첨자)를 지정해 주면 해당 데이터타입의 값을 저장할 수 있는 저장공간을 길이 갯수만큼 "연속" 할당한다. 배열의 선언과 생성은 한줄로 가능하다. 예를 들어, 길이가 3인 문자열(String) 배열을 생성한다면

String[] strArr = new String[3];

2. Array 의 초기화

배열 공간 할당과 동시에 초기값을 기록하는 것을 말하며, 배열 초기화시에는 배열의 길이를 따로 지정하지 않고 초기화에 사용되는 값의 개수가 자동 배열의 길이로 처리된다.

자바에서는 배열공간의 초기화를 따로 지정하지 않아도 자동 초기화 처리가 되도록 각 자료형별 기본값이 준비되어 있다. (boolean -> false , char -> '\u0000' , 정수형 -> 0 , 실수형 -> 0.0 , 참조형 -> null)

데이터타입[] 배열참조변수 = {값1, 값2, 값3, ...};
데이터타입[] 배열참조변수 = new 데이터타입[]{값1, 값2, 값3, ...};

 

3. Array 의 인덱스

생성된 배열 공간의 각 저장공간을 요소(element) 라고 부르며 '배열이름[인덱스]'형식으로 요소에 접근할 수 있다. 

배열의 저장공간의 개수를 배열의 길이(length)라고 하며, 인덱스는 '0'부터 시작해서 '배열의 길이-1' 까지 지정된다.

Arr[0 ~ lenth-1]

 

그러면 다음 코드를 통해 위의 개념들을 확인해 보겠다.

package com.test01;

import java.util.Arrays;

public class MTest01 {

	// Array : (같은 타입의)여러개의 값을 효과적으로 관리하기 위한 객체
	
	public static void main(String[] args) {
		// 방법1
		int[] a; // 선언
		a = new int[5]; // 정의

		a[0] = 1; // 초기화
		a[1] = 2;
		a[2] = 3;
		a[3] = 4;
		a[4] = 5;
		System.out.println(a[1]);

		// 방법2
		// 선언 = 정의 = 초기화
		int[] b = new int[] { 6, 7, 8, 9, 10 };
		System.out.println(b[1]);

		// 방법3
		// 선언 초기화
		int c[] = { 11, 12, 13, 14, 15, 16, 17 };
		System.out.println(c[1]);
		System.out.println(c);
		// prn(c);

		// 와우;;;;
		System.out.println(Arrays.toString(c));

		String[] s = new String[] { "have", "a", "nice", "day" };
		test(s);
	}

	private static void test(String[] s) {
		// nice -> good 으로 바꾸고
		// [have, a, good, day] 로 출력
		// 단. Arrays 클래스를 사용하지 말 것!

		s[2] = "good";

		System.out.print("[");
		for (int i = 0; i < s.length; i++) {
			System.out.print(s[i]);
			if (i < s.length - 1)
				System.out.print(", ");
		}
		System.out.println("]");

		// ==

		System.out.println(Arrays.toString(s));

	}

	private static void prn(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.printf("%3d", arr[i]);
		}
	}
}

Arrays객체의 toString() 메서드를 통해 배열의 모든 인덱스의 값들을 출력할 수 있다. 간단한 출력에 유용하게 사용할 수 있다.

 

다차원 Array

같은 자료형 변수들의 묶음을 1차원 배열이라 하고, 자료형이 같은 1차원 배열들의 묶음을 2차원 배열이라고 한다.

1차원 배열은 배열기호[] 가 1개이며 2차원 배열은 배열기호가 [][] 2개이다.

같은 자료형 2차원 배열들의 묶음을 3차원 배열이라고 하며 배열기호는 [][][] 3개로 표시된다. 

이러한 2차원 이상의 배열들을 다차원 배열이라고 한다.

 

1. 2차원 배열의 선언

데이터타입 배열참조변수[][];
데이터타입[] 배열참조변수[];
데이터타입[][] 배열참조변수;

 

2. 2차원 배열의 생성

배열참조변수 = new 데이터타입[행길이][열길이];    //정변배열
배열참조변수 = new 데이터타입[행길이][];         //가변배열, 행 만 선언
배열참조변수[행인덱스] = new 데이터타입[열길이];  //행에대한 열 선언

행길이는 묶여질 1차원 배열의 개수를 의미하고, 열길이는 각 1차원 배열의 값 개수를 의미한다.

 

3. 2차원 배열의 초기화

데이터타입 배열이름[][] = {{0행0열값, 0행1열값, ...}, {1행0열값, 1행1열값, ...}, ...};

 

그러면 다음 코드를 통해 위의 개념들을 확인해 보겠다.

package com.test01;

import java.util.Arrays;

public class MTest02 {

	public static void main(String[] args) {
		// 방법 1
		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
		int[][] b = new int[3][];
		b[0] = new int[5];
		b[1] = new int[7];
		b[2] = new int[2];

		// 방법 3
		int[][] c = new int[][] { { 1, 2, 3 }, { 4, 5, 6, 7, 8 }, { 9 }, { 10, 11 } };

		// 방법 4
		int[][] d = { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10, 11, 12, 13 }, { 14, 15, 16 } };

		// 3차원 배열
		int[][][] e = { { { 1, 2 }, { 3, 4, 5 } }, { { 6, 7 }, { 8, 9, 10 }, { 11, 12, 13 } },
				{ { 14 }, { 15 }, { 16 } } };
		System.out.println(Arrays.deepToString(e));

		System.out.println(d);

		prn(d);

		String[][] s = { { "have", "a", "nice", "day" }, { "너무", "어려워" }, { "배열", "이차원 배열" } };
		test(s);
	}

	private static void test(String[][] s) {
		/*
		 * nice -> good
		 * 어려워 -> 쉬워
		 * 이차원 배열 -> 다차원 배열
		 * 로 바꿔서 전체 출력
		 */
		
		s[0][2] = "good";
		s[1][1] = "쉬워";
		s[2][1] = "다차원 배열";
		
		System.out.println(Arrays.deepToString(s));
		
		
	}

	private static void prn(int[][] d) {
		for (int i = 0; i < d.length; i++) {
			for (int j = 0; j < d[i].length; j++) {
				System.out.print(d[i][j] + " ");
			}
			System.out.println();
		}

		// == 

		System.out.println(Arrays.deepToString(d));
	}

}

 

예제1) 정답 : 

package com.test01;

public class MTest03 {

	/*
	 * 1. a~z의 값을 일차원 배열에 저장하고 다음과 같이 출력하자
	 * 
	 * 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
	 */

	/*
	 * 2. 위에서 만든 배열을 거꾸로 출력하자.
	 * 
	 * z y x w v u 
	 * t s r q p o ...
	 */

	/*
	 * 3. 1번에서 만든 배열을 대문자로 바꿔서 출력하자.
	 */
	public static void main(String[] args) {

		String arr = "";
		for (char i = 'a'; i <= 'z'; i++) {
			arr += i;
		}

		prn01(arr);
		System.out.println("\n================================");
		prn02(arr);
		System.out.println("\n================================");
		prn03(arr);

	}

	private static void prn03(String arr) {
		// Character.toUpperCase(arr[index]) 사용해도 가능!!!
		arr = arr.toUpperCase();
		char[] arrCh = arr.toCharArray();

		for (int i = 1; i <= arrCh.length; i++) {

			System.out.print(arrCh[i - 1]);
			if (i % 6 == 0)
				System.out.println();
		}
	}

	private static void prn02(String arr) {
		// TODO Auto-generated method stub
		char[] arrCh = arr.toCharArray();

		int count = 0;
		for (int i = arrCh.length - 1; i >= 0; i--) {

			System.out.print(arrCh[i]);
			count++;
			if (count % 6 == 0)
				System.out.println();
		}
	}

	private static void prn01(String arr) {
		// TODO Auto-generated method stub
		char[] arrCh = arr.toCharArray();

		int count = 0;
		for (int i = 0; i < arrCh.length; i++) {

			System.out.print(arrCh[i]);
			count++;
			if (count % 6 == 0)
				System.out.println();
		}
	}
}

예제2) 정답 :

package com.test04;

import java.util.Random;

public class MTest {
	/*
	 * 1. 5칸짜리 int형 1차원 배열을 만들자.
	 * 
	 * 2. 반복문을 사용하여 해당 배열의 앞에서 4개에 5~9사이의 랜덤 숫자를 각각 대입
	 * 
	 * 3. 배열의 4번째 위치한 인덱스에 앞의 4개의 모든 값들을 곱해서 저장
	 * 
	 * 4. 배열을 출력하자.
	 * 
	 * 5. 배열 안의 모든 값을 더해서 출력하자
	 */
	public static void main(String[] args) {
		int[] arr = new int[5];
		
		prn01(arr);
		prn02(arr);
		prn03(arr);
		prn04(arr);
	}

	private static void prn04(int[] arr) {
		// TODO Auto-generated method stub
		int sum = 0;
		for(int i=0;i<arr.length;i++)
			sum += arr[i];
		System.out.println("sum of arr = " + sum);
		System.out.println("=====================");
	}

	private static void prn03(int[] arr) {
		// TODO Auto-generated method stub
		for(int i=0;i<arr.length;i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println("\n=====================");
	}

	private static void prn02(int[] arr) {
		// TODO Auto-generated method stub
		int mul = 1;
		for(int i=0;i<4;i++)
			mul *= arr[i];
			
		arr[4] = mul;
		
		System.out.println("multiflex of arr[0~3] = " + arr[4]);
		System.out.println("=====================");
	}
	
	private static void prn01(int[] arr) {
		// TODO Auto-generated method stub
		Random r = new Random();
		
		for(int i=0;i<4;i++) {
			arr[i] = r.nextInt(5) + 5;
		}
			
		for(int i=0;i<arr.length;i++) {
			System.out.print(arr[i] + " ");
		}
		
		System.out.println("\n=====================");
	}
	
	
}

Array의 복사

1. shallow copy (얕은 값 복사) : 주소값을 복사하여 메모리상의 같은 데이터를 두 변수가 참조한다. 복사본에서 수정하면 원본도 수정

package com.test02;

import java.util.Arrays;

public class ShallowCopy {

	/*
	 * 얕은 값 복사
	 * 
	 * 메모리상의 같은 부분을 두 변수가 참조
	 */
	public static void main(String[] args) {
		int[] original = { 10, 20, 30, 40, 50 };
		int[] copy = original;
		
		System.out.println(Arrays.toString(original));
		System.out.println(Arrays.toString(copy));
		
		System.out.println(original == copy);	//참조하는 메모리가 같아 true
		
		copy[0] = 100;
		
		System.out.println(Arrays.toString(original));
		System.out.println(Arrays.toString(copy));
		
		System.out.println("=========================================");
		
		//hashcode : 객체의 주소값
		System.out.println(original.hashCode());
		System.out.println(copy.hashCode());
		
		
		
	}
}

서로 다른 두 변수의 주수값 hashCode() 를 출력하면 같은 값이 나오는 것을 확인할 수 있다.

2. deep copy (깊은 값 복사) : 값 자체를 복사해서 새로운 배열을 만든다. 복사본을 수정해도 원본에는 영향을 미치지 않음

package com.test02;

import java.util.Arrays;

public class DeepCopy {

	/*
	 * 깊은 값 복사
	 * 
	 * 메모리상에서 객체를 복사해 새로운 객체를 만듬, 참조는 각각
	 * 복사본을 변경해도 원본에 영향이 없음
	 */
	public static void main(String[] args) {

		int[] original = { 10, 20, 30, 40, 50 };

		// 방법 1. 배열 인덱스의 값을 가져와서 복사
		int[] copyOne = new int[original.length];
		for (int i = 0; i < original.length; i++) {
			copyOne[i] = original[i];
		}
		System.out.println(Arrays.toString(original));
		System.out.println(Arrays.toString(copyOne));
		System.out.println(original == copyOne); // 참조하는 메모리가 다르기때문에 false
		System.out.println(Arrays.equals(original, copyOne)); // true

		copyOne[0] = 100;

		System.out.println(Arrays.toString(original));
		System.out.println(Arrays.toString(copyOne));
		System.out.println(original == copyOne);
		System.out.println(Arrays.equals(original, copyOne));

		System.out.println("=========================================");

		// 방법 2. original 한테 요청하여 복사 clone()
		int[] copyTwo = original.clone();
		System.out.println(Arrays.toString(original));
		System.out.println(Arrays.toString(copyTwo));
		System.out.println(original == copyTwo);
		System.out.println(Arrays.equals(original, copyTwo));

		System.out.println("=========================================");

		// 방법 3. System을 사용하여 복사
		int[] copyThree = new int[original.length];
		// fill() 메서드는 해당 배열을 원하는 값 (4) 로 다 채워버림 초기화에 굳!!!
		Arrays.fill(copyThree, 4);
		System.out.println(Arrays.toString(copyThree));

		// System.arrayCopy(원본 배열 객체, 원본 시작위치, 복사 배열 객체, 복사 시작위치, 복사할 개수);
		System.arraycopy(original, 0, copyThree, 2, 2);
		System.out.println(Arrays.toString(copyThree));
		// 10 20 30 40 50
		// 4  4  10 20 4

		System.out.println("=========================================");
		
		//hashcode : 객체의 주소값
		System.out.println(original.hashCode());
		System.out.println(copyOne.hashCode());
		System.out.println(copyTwo.hashCode());
		System.out.println(copyThree.hashCode());

	}
}

각 변수의 주소값 hashCode() 가 각기 다른것을 볼 수 있다.

 

객체 Array

배열 안에는 기본 타입 뿐 아니라 객체 또한 담길 수 있다. 객체가 들어간 배열을 객체 배열이라 칭한다.

 

배열에 담을 객체 class

package com.test03;

public class Person {

	public String name;
	public int age;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
}

객체 배열

package com.test03;

import java.util.Arrays;

public class MTest {

	public static void main(String[] args) {
		// 객체 배열 = 객체가 들어간 배열
		Person[] qClass = new Person[10];
		
		Person lee = new Person("이순신", 33);
		Person hong = new Person("홍길동", 19);
		Person cho = new Person("조태호", 40);

		qClass[0] = lee;
		qClass[1] = hong;
		qClass[2] = cho;		

		//나머지는 for loop 로 초기화
		for (int i = 3; i < qClass.length; i++) {
			qClass[i] = new Person("박찬호", 100);
		}

		for (int i = 0; i < qClass.length; i++) {
			System.out.println(qClass[i].getName() + " " + qClass[i].getAge());
		}
	}
}

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함