[Java] 05_배열(Array)

2022. 8. 3. 10:29·📗 self-study/📗 KH정보교육원 당산지원

05_배열(Array)

 

 

변수: 메모리에 값을 저장할 수 있는 공간(상자, 박스) => 종류에 맞는 값, 변수에는 한 번에 한 개의 값만 대입 가능

배열: 메모리에 값을 저장할 수 있는 공간(상자, 박스) => 종류에 맞는 값, 배열에는 한 번에 여러 개의 값을 대입 가능

=> 배열은 저장된 값마다 인덱스 번호(방 번호)가 0부터 시작하여 설정

 

배열도 참조 변수다! => stack에 주소값이 들어가 있음!

*변수: "자료형에 맞는 값 하나만" 담을 수 있는 개념
  예) int a =10; // a == 10
               a = 20; // a == 20
 
*배열: "자료형에 맞는 값 여러 개"를 담을 수 있는 개념
예) int[] b = new int[3]; // int형의 값이 들어갈 수 있는 방을 3개 만들겠다
방 [0], [1], [2] 호실이 만들어짐
인덱스는 항상 0에서부터 시작한다
문자열의 크기가 5라면, 마지막 인덱스 = 4 (0, 1, 2, 3, 4)
배열의 크기가 3이라면, 마지막 인덱스 = 2 (0, 1, 2)
배열의 크기가 7이라면, 마지막 인덱스 = 6 (0, 1, 2, 3, 4, 5, 6)
항상 크기 = n, 마지막 인덱스 = n - 1 공식을 외워 두자!   

=> for문에서 반복 횟수를 지정하는 가장 기본적인 방법
 int i = 0; i  <  횟수; i++

*변수 출력 시 반복문 활용할 수 없지만 배열은 반복문 사용 가능함!

package com.kh.array;

public class A_Array {
	
	public void method1() {
		
		// 배열을 왜 써야 할까?
		// 변수만을 이용해서 프로그래밍을 하게 되면...
		// 0, 1, 2, 3, 4를 기록해야 함
		
		/*
		int num1 = 0;
		int num2 = 1;
		int num3 = 2;
		int num4 = 3;
		int num5 = 4;
		
		// 출력할 때는? => 일일이 출력해야 한다. 반복문 사용 불가!
		
		System.out.println(num1);
		System.out.println(num2);
		System.out.println(num3);
		System.out.println(num4);
		System.out.println(num5);
		
		for(int i = 1; i <= 5; i++) {
			
			// System.our.println(numi); // numi라는 변수 없다는 오류 뜸
			// System.out.println("num" + i); // num이라는 문자열 + i값이 문자열로 출력됨 num1, num2 ...
		}
		
		// 총 합계 구할 때는? => 일일이 더해 줘야 한다. 반복문 사용 불가!
		int sum = num1 + num2 + num3 + num4 + num5;
		*/
		
		// 만약 기록해야 하는 변수가 100, 1000, 10000개로 늘어난다면?
		
		// 배열을 가지고 프로그래밍하기
		// 0, 1, 2, 3, 4을 기록해야 함
		
		/*
		 * 1. 배열 선언 "나 배열 쓸 거야!" => 상자 생성
		 * [ 표현법 ] => 두 가지 표현법이 있음
		 * 자료형 배열명[];
		 * 자료형[] 배열명; 
		 */
		
		// int a; // 변수를 선언
		// int arr[]; // 배열을 선언
		// int[] arr;
		
		/*
		 * 2. 배열 할당 "이만큼 쓸 거야!" => 상자 칸 생성, 이 과정까지 거쳐야 원하는 만큼의 빈 상자가 만들어짐
		 * 이 배열에 지금부터 몇 개의 값들을 묶어서 보관할 것인지 배열의 크기를 지정해 주는 과정
		 * 지정한 이 개수만큼 값이 들어갈 방이 만들어짐
		 * 
		 * [ 표현법 ]
		 * 배열명 = new 자료형[배열크기];
		 */
		
		// arr = new int[5];
		
		// 변수 선언 및 초기화 한 큐에!
		
		int a = 1;
		
		// 배열 선언 및 할당 한 큐에!
		int[] arr = new int[5];
		
		// => 이 과정까지 거치지 않는다면 절대로 배열을 사용할 수 없음!
		
		/*
		 * 3. 배열의 각 인덱스 방 자리에 값 대입
		 * [ 표현법 ]
		 * 배열명[인덱스] = 값;
		 */
		
		arr[0] = 0;
		arr[1] = 1;
		arr[2] = 2;
		arr[3] = 3;
		arr[4] = 4;
		
		// 배열의 출력 => 반복문 활용이 가능!
		
		/*
		System.out.println(arr[0]);
		System.out.println(arr[1]);
		System.out.println(arr[2]);
		System.out.println(arr[3]);
		System.out.println(arr[4]);
		*/
		
		for (int i = 0; i < 5; i++) {
			
			System.out.println(arr[i]);
		}
		
		
	// 총 합계 구하기
		int sum = 0;
		for(int i = 0; i < 5; i++) {
			
			sum += arr[i];
		}
			System.out.println("sum: " + sum);
            
			System.out.println(arr[0]); // 0
			System.out.println(arr); // [I@6d06d69c == 주소값
		
	}
	
}

주소값 [I@6d06d69c => [ : 배열, I: int형

 

	public void method2() {
		
		int i = 10;
		
		int[] iArr = new int[5];
		
		System.out.println("i: " + i);
		System.out.println("iArr: " + iArr);
		System.out.println("iArr의 해시코드값: " + iArr.hashCode());
		// 해시코드: 주소값을 10진수의 형태로 보여 주는 개념
		
		double[] dArr = new double[3];
		System.out.println("dArr: " + dArr);
		System.out.println("dArr의 해시코드 값: " + dArr.hashCode());
		
		/*
		 * 기본 자료형: boolean, char, byte, short, int, long, double
		 * => stack 영역에 실제 값을 바로 담을 수 있는 변수 => 일반 변수
		 * 
		 * 그 이외의 자료형: String, int[], double[], short[], byte[], Scanner, A_Array(내가 만든 클래스), ...
		 * => new를 쓰는 변수들 // stack 영역에 주소값을 담고 있는 변수(실제 값은 heap 영역에 담겨 있음) => 참조 변수(레퍼런스 변수)
		 */
		
	}


배열의 선언과 동시에 할당
자료형[] 배열명 = new 자료형[사이즈];

	public void method3() {
		
		int[] iArr = new int[3]; // iArr 에는 주소값이 대입되어 있고, heap영역에는 [0], [1], [2] 방 생성
		double[] dArr = new double[3]; // [0], [1], [2]
		
		// System.out.println(iArr[0]);
		
		// 배열을 출력할 때 반복문을 쓰면 더 유리함
		// 0번 인덱스부터 마지막 인덱스까지 순차적으로 출력 가능
		// 마지막인덱스 == 배열의크기 - 1
		
		// 배열의 크기를 아는 방법
		// [ 표현법 ] 배열명.length
		// => 주의할 점! 여기서의 length는 메소드가 아님! 소괄호 안 들어감!
		System.out.println("iArr 배열의 크기: " + iArr.length);
		System.out.println("dArr 배열의 크기: " + dArr.length);
		
		/* 내가 배열의 크기를 알고 있으므로 조건식을 이렇게 써도 되긴 하지만
		 * 이렇게 쓰면 나중에 코드를 바꾸거나 할 때 티가 안 남!
		for (int i = 0; i < 3; i++) {
			
			System.out.println(iArr[i]);
		}
		*/
		
		for(int i = 0; i < iArr.length; i++) {
			
			System.out.println(iArr[i]);
		}
		
		for (int i = 0; i < dArr.length; i++) {
			System.out.println(dArr[i]);
		}
		
		/*
		 * 각각의 인덱스에 값을 대입하지 않아도 뭔가 담겨 있음!
		 * int형 배열에는 정수 0, double형 배열에는 실수 0.0이 담겨 있음
		 * 
		 * => 메모리의 heap 영역에서는 절대 빈 공간으로 존재할 수 없음
		 * 	    배열이 만들어짐과 동시에 JVM에 의해서 기본값으로 초기화가 진행됨
		 */

	}

 

	public void method4() {
		
		int[] arr = new int[5]; // 4*5= 20byte [0], [1], [2], [3], [4]
								//  현재 채워진 값    0    0    0    0    0   
		/*
		arr[0] = 1;
		arr[1] = 2;
		arr[2] = 3;
		arr[3] = 4;
		arr[4] = 5;
		
		arr[10] = 10;
		// ArrayIndexOutOfBoundsException: 10
		// 배열의 인덱스 범위를 벗어남
		// 10번 인덱스에서 오류가 발생
		
		// => 내가 한 번 배열을 만들었으면 그 사이즈 범위를 벗어난 곳은 이용할 수 없음
		// 	    제한된 범위 안에서만 이용 가능함
		*/
		
		// 값 대입을 위한 for문
		for(int i = 0; i < arr.length; i++) {
			
			arr[i] = i + 1;

		}
		
		// 값 출력과 동시에 누적 덧셈을 해 주는 for문
		int sum = 0;
		
		for(int i = 0; i < arr.length; i++) {
			
			System.out.println(arr[i]); // 1 2 3 4 5
			sum += arr[i];
			
		}
		
		System.out.println("총 합계: " + sum); // 총 합계: 15
		
		System.out.println("arr: " + arr); // 주소값 [I@6d06d69c
		System.out.println("arr: " + arr.hashCode()); // 주소값의 해시코드 1829164700
		
	}

 

public void method5() {
		
		// 배열에 각 랜덤한 수를 대입
		
		int[] arr = new int[10]; // [0], [1], ... , [9]
		
		// 0번 인덱스에서부터 마지막 9번 인덱스까지 51 ~ 100 사이의 랜덤값
		
		for(int i = 0; i < arr.length; i++) {
			
			arr[i] = (int)(Math.random() * 50) + 51;
			
		}
		
		// 잘 담겨 있나 출력용 반복문
		// arr[x]: xx 형식 출력
		
		for(int i = 0; i < arr.length; i++) {
			System.out.printf("arr[%d]: %d \n", i, arr[i]);
		}
		
		// 랜덤한 숫자 (1 ~ 45)를 중복 없이 6개를 뽑을 수 있는 프로그램? => 로또 // 오늘 숙제
        
        }

 

public void method6() {
		
		int[] arr = new int[5];
		
		System.out.println(arr);
		System.out.println("arr의 해시코드값: " + arr.hashCode());
		
		/*
		arr[0] = 2;
		arr[1] = 4;
		arr[2] = 6;
		arr[3] = 8;
		arr[4] = 10;
		*/
		
		// 대입
		
		int value = 2; // 값 대입용 일종의 초기식
		for(int i = 0; i < arr.length; i++) {
			
			// arr[i] = (i + 1) * 2; // 2, 4, 6, 8, 10 
			arr[i] = value;
			value += 2;
		}
		
		for(int i = 0; i < arr.length; i++) { 
			
			System.out.println(arr[i] + " ");
			
		}
        
		// arr[5] = 12;
		// arr[6] = 14; // ArrayIndexOutOfBoundsException: 5
		// => 이미 배열의 크기를 할당했는데 공간이 더 필요해졌다면?
		
		/*
		 * 배열의 가장 큰 단점
		 * 한 번 지정한 배열의 크기에 따라 제한적으로 사용됨
		 * 한 번 지정한 배열의 크기를 변경 불가(지정한 이외의 인덱스 방 번호는 쓸 수 없음)
		 * => 배열의 크기를 변경하고자 한다면 어쩔 수 없이 새로운 배열을 만들어야 함(재할당)
		 */
		
		arr = new int[7]; // 재할당
        
        		System.out.println();
                
		System.out.println("===== arr 변경 후 =====");
		System.out.println(arr);
		System.out.println("arr의 해시코드값: " + arr.hashCode());
		
		/*
		 * 메모리 영역은 항상 고유한 주소값을 가지고 있음, 할당 시 기존에 부여되었던 주소값과 절대 겹치지 않음
		 * 새롭게 배열을 할당만 다시 한다면
		 * 기존에 참조하고 있던 연결이 끊어지고 새로운 곳을 참조하게 됨
		 * 연결이 끊어진 기존의 배열의 heap 영역에 일단 동동 떠다님
		 * 일정 시간이 지나면 "가비지 컬렉터"에 의해 정리됨 = 가비지 컬렉션(자동 메모리 관리)
		 */
         
         		// 참고) 현재 연결되어 있는 고리만 끊고자 한다면?
		
		arr = null; // null: "없음"을 의미하는 값
		
		System.out.println(arr); // null 출력
		
		// arr[0] = 10;
		// NullPointerException: 주소가 없는데 어떻게 접근해서 연산할래?
		//						  라고 알려 주는 오류
		
		// System.out.println(arr.hashCode());
		
		/*
		 * 기본 자료형의 기본값은 다음과 같음
		 * 정수형: 0
		 * 실수형: 0.0
		 * 문자형: ' '
		 * 논리형: false
		 * 
		 * 참조 자료형의 기본값은 다음과 같음
		 * null: "없음"을 나타내는 값 => "주소값이 없다"
		 */
     }

 

arr = new int[7]

// 재할당 하는 순간 배열 7개짜리의 박스가 heap 영역에 생성됨

(아직 초기화하지 않았으니 JVM에 의해 빈 박스에는 0이 들어간 상태)

-> 기존 0123의 배열 5개짜리 박스와의 연결고리가 끊어짐

-> heap 영역의 배열 7개짜리 박스 주소값이 stack 영역의 arr에 저장됨

 

버려진 5개짜리 배열은 heap 영역 안에 동동 떠다니다가 일정 시간이 지난 뒤 GC(Garbage Collector: 청소부, 치우는 놈)에 의해 사라지게 됨

= GC(Garbage Collection, 연결이 끊어진 필요 없는 데이터가 사라지는 행위)

 

public void method7() {
		
		// 3명의 사용자에게 매번 키의 정보를 double로 입력받고 배열에 담아 두고
		// 3명의 키 정보를 반복문을 이용하여 출력
		// 3명의 키 정보의 합계, 평균(총 합계 / 개수)
		
		Scanner sc = new Scanner(System.in);
		
		double[] heights = new double[3]; // [0], [1], [2]
		
		for(int i = 0; i < heights.length; i++) { // 고정
			
			System.out.printf("사용자 %d의 키(cm)를 입력하세요: ", (i+1));
			heights[i] = sc.nextDouble();
			
			sc.nextLine();
				
		}
		
		// 3명의 키 정보를 출력, 합계도 같이 구하기
		
		double sum = 0.0;
		for(int i = 0; i < heights.length; i++) {
			
			System.out.printf("사용자 %d의 키는 %f입니다 \n", (i+1), heights[i]);

			sum += heights[i];

		}

		System.out.println("3명의 키 정보 합계: " + sum);
		System.out.println("3명의 키 정보 평균: " + (sum / heights.length));
		
	}
	// 실습 문제
	
	public void method8() {
		
		// 사용자에게 문자열을 하나 입력받은 후
		// 각각의 문자들을 char 배열에 옮겨 담기
		
		Scanner sc = new Scanner(System.in);
		
		
		System.out.print("문자열을 입력하세요: ");
		String str = sc.nextLine();
		
		// 어떤 문자열을 입력받을지 모르기 때문에 문자열을 길이를 가늠할 수 없음!
		// => 문자열의 길이만큼의 방을 갖는 char 배열 만들기 ( 배열 크기 == 문자열의 길이 )
		
		// 한 큐에 char[] arr = new char[str.length()]; 쓰는 거 헷갈린다면!
		int length = str.length();
		char[] arr = new char[length]; // [0], [1], [2], ..., [length -1]
		
		// 할 만하다 싶으면 이렇게 1줄로 줄일 수도 있음!
		// char[] arr = new char[str.length()]; // [0], [1], [2], ..., [length -1]
		
		// 문자열로부터 각 인덱스 자리의 문자를 추출해서 각 배열의 방에 담기
		
		/*
		arr[0] = str.charAt(0);
		arr[1] = str.charAt(1);
		arr[2] = str.charAt(2);
		*/
		
		for(int i = 0; i < length; i++) {
			
			arr[i] = str.charAt(i);
			
		}
		
		// char 배열의 각 인덱스에 접근해서 값이 잘 담겨 있는지 출력
		for(int i = 0; i < arr.length; i++) {
		// for(int i = 0; i < length; i++) { // arr.length가 곧 length이므로 그냥 length로 써도 무방함!
			
			System.out.println(arr[i]);
		}
		
	}
	public void method9() {
		
		// 배열 선언
		int[] arr1;
		
		// 배열 할당
		arr1 = new int[5];
		
		// 배열의 선언과 할당
		int[] arr = new int[4];
		
		// 배열의 각 인덱스에 값 대입
		arr[0] = 1; // 처음 대입하는 거니까 얘네는 초기화라고도 볼 수 있음!
		arr[1] = 2;
		arr[2] = 3;
		arr[3] = 4;
		
		// 배열 선언과 할당을 하는 동시에 값을 초기화(대입)까지 한 번에 끝내는 방법 2가지
		// 배열에 고정된 값을 넣어 놓은 상태로 시작하고 싶을 때 유용함!
		
			// 방법 1.
			int[] arr2 = new int[] {1, 2, 3, 4};
			
			// 방법 2.
			int[] arr3 = {1, 2, 3, 4};
			
		// 배열 비교
		System.out.println(arr == arr2); // false
		System.out.println(arr2 == arr3); // false
		System.out.println(arr3 == arr); // false
		// => 주소값 간의 동등 비교이기 때문에 false가 나옴!!
		// (String 과 마찬가지)
		
	}

실습 문제다요

	public void method10() {
		
		/*
		 * 실습 문제
		 * 좋아하는 과일의 개수를 입력받아
		 * 그만큼 반복을 돌리면서 과일명을 입력받기 => 입력받을 때마다 문자열 배열에 담고 출력
		 */
		
		Scanner sc = new Scanner(System.in);
		
		System.out.print("좋아하는 과일의 개수를 입력하세요: ");
		int num = sc.nextInt();
		sc.nextLine();
		
		String[] fruits = new String[num];
		
		for(int i = 0; i < fruits.length; i++) {
			System.out.printf("좋아하는 %d번째 과일명을 입력하세요: ", i+1);
			
			fruits[i] = sc.nextLine();

		}
		
		for(int i = 0; i < num; i++) {
			
			System.out.printf("사용자가 좋아하는 %d번째 과일의 이름은 %s입니다.\n", i+1, fruits[i]);

		}
		
	}
	
	public void method11() {
		
		/*
		 * 로또 생성 자동 프로그램을 만드세요
		 * 
		 * 힌트
		 * 1 ~ 45까지의 임의의 수를 "중복 없이" 6개 발생시켜 각 배열에 담으시면 됩니다
		 */
		
		int[] lotto = new int[6]; // [0], [1], [2], [3], [4], [5]
		
		for(int i = 0; i < lotto.length; i++) { // 위쪽 for문 한 번 돌고, 밑 for문 i-1만큼 반복하다가 다시 올라와서 위쪽 for문 진행됨
			
			lotto[i] = (int)(Math.random() * 45) + 1;
			
			for(int j = 0; j < i; j++) { // 원활한 이해를 위해서 조건식을 j <= i-1 라고 써도 무방하나, 깔끔한 코드를 위해 j < i로 작성!
				
				if(lotto[i] == lotto[j]) {
					i--;
				}
					break; 
				
			}
				
			}
		//  Arrays.sort(lotto); // 오름차순 정렬하고 싶을 때 추가하면 됨!
		System.out.println("로또 번호는 " + Arrays.toString(lotto) + " 입니다.");
		
	}

arr, arr2, arr3은 서로 다른 주소값을 가지고 있는 상태

 

배열 복사

1) 얕은 복사 - 복사하는 시늉만 내는 개념(같은 주소값을 참조하게 함)

얕은 복사

// 얕은 복사
	public void method1() {
		
		// 복사: 원본을 본떠서 만들겠다
		// => 이 테스트는 원본 배열이 있어야지만 가능함!
		
		// 원본 배열
		int[] origin = {1, 2, 3, 4, 5};
		
		System.out.println("== 원본 배열 출력 ==");
		for(int i = 0; i < origin.length; i++) {
			System.out.print(origin[i] + " ");
		}
		
		// 복사열 배열: 원본으로부터 복사를 떠서 만들 예정
		int[] copy = origin;
		
		System.out.println("\n== 복사본 배열 출력 ==");
		for(int i = 0; i < copy.length; i++) {
			System.out.print(copy[i] + " ");
		}
		
		// 복사본 배열 출력
		copy[2] = 99;
		
		System.out.println("\n== 복사본 배열 출력 수정 후 ==");
		for(int i = 0; i < copy.length; i++) {
			System.out.print(copy[i] + " ");
		}
		
		// 원본 배열 출력 -> 카피본을 바꿨는데 원본은 잘 남아 있는지를 확인
		
		System.out.println("\n== 복사본 배열을 수정 후의 원본 ==");
		for(int i =0; i < origin.length; i++) {
			System.out.print(origin[i] + " ");
		}
		
		// 복사본 배열만을 가지고 수정을 했는데 원본 배열의 내용도 같이 수정이 된 것 같다.
		// => 원본 배열도 함께 값이 변경된 것을 알 수 있다.
		// 얕은 복사: 배열의 주소값이 복사되어 원본과 복사본이 같은 상태
		
		System.out.println("\n원본 배열의 해시코드값: " + origin.hashCode());
		System.out.println("복사본 배열의 해시코드값: " + copy.hashCode());
		
	}

주소값만 공유하므로 copy본 수정 시 원본도 수정됨

 

2) 깊은 복사 - 찐 복사 개념

=> 4가지 방법이 있음

깊은 복사

첫 번째 방법

for문

	public void method2() {
		// 1. for문을 이용하는 방법
		// 새로운 배열을 선언 및 할당까지 끝낸 다음에
		// 원본 배열로부터 일일이 다 for문을 이용해서 옮겨 대입하는 방법
		
		// 원본 배열
		int[] origin = {1, 2, 3, 4, 5};
		
		// 복사본 배열
		int[] copy = new int[origin.length]; // 각 방은 기본값인 0으로 초기화된 상태
		
		/*
		 * copy[0] = origin[0];
		 * copy[1] = origin[1];
		 * ...
		 */
		for (int i = 0; i < copy.length; i++) {
			copy[i] = origin[i];
		}
		
		System.out.println("== 복사본 배열 출력 ==");
		for(int i = 0; i < copy.length; i++) {
			System.out.print(copy[i] + " ");
		}
		
		copy[2] = 99;
		
		System.out.println("\n==복사본 배열 수정 후 ==");
		for(int i = 0; i < copy.length; i++) {
			System.out.print(copy[i] + " ");
		}
		
		System.out.println("\n== 복사본 배열 수정 후의 원본 ==");
		for(int i = 0; i < origin.length; i++) {
			System.out.print(origin[i] + " ");
		}
		
		System.out.println("\n원본 배열의 해시코드값: " + origin.hashCode());
		System.out.println("복사본 배열의 해시코드값: " + copy.hashCode());
		
	}

int[] copy = new int[origin.length]; // 각 방은 기본값인 0으로 초기화된 상태

 

copy[2] = 99; // 원본은 바뀌지 않음

 

 

두 번째 방법

System.arraycopy(src, srcPos, des, desPos, length);

System.arraycopy(원본배열명, 원본시작할인덱스, 복사본 배열명, 복사본시작할 덱스, 복사할개수);

	public void method3() {
		
		// 2. 새로운 배열을 생성 (선언 및 할당) 후
		//	  system 클래스에서 제공하는 arraycopy 메소드를 호출하여 복사
		
		// 원본 배열
		int[] origin = {1, 2, 3, 4, 5};
		
		// 복사본 배열
		int[] copy = new int[10]; // origin의 사이즈 그대로가 아닌 넉넉하게~ 0 0 0 0 0 0 0 0 0 0 
		
		// System 클래스의 arraycopy 메소드 사용법
		// [ 표현법 ]
		// System.arraycopy(원본배열명, 원본배열의복사를시작할인덱스, 복사본배열명, 복사본배열의복사시작할인덱스, 복사할개수);
		// System.arraycopy(src(원본배열명), srcPos(pos:position, 원본 어디서부터?, 원본 시작할 인덱스), dest(destination:목적지, 복사본 배열명), destPos(복사본 어디서부터?, 복사본 시작할 인덱스), length(총 몇 개를 복사? 복사할개수);
		
		System.arraycopy(origin, 0, copy, 0, 5); // 1 2 3 4 5 0 0 0 0 0
		// System.arraycopy(origin, 0, copy, 2, 5); // 0 0 1 2 3 4 5 0 0 0
		// System.arraycopy(origin, 0, copy, 1, 3); // 0 1 2 3 0 0 0 0 0 0
		// System.arraycopy(origin, 2, copy, 1, 3); // 0 3 4 5 0 0 0 0 0 0
		// System.arraycopy(origin, 2, copy, 9, 2); // 0 0 0 0 0 0 0 0 0 3 (4) ???
		// ArrayIndexOutOfBoundsException => 복사하는 과정에서 인덱스 범위를 벗어나서 발생
				
		System.out.println("== 복사본 배열 출력 ==");
		for(int i = 0; i < copy.length; i++) { 
			System.out.print(copy[i] + " ");
		}
		
		System.out.println("\n원본 배열의 해시코드값: " + origin.hashCode());
		System.out.println("복사본 배열의 해시코드값: " + copy.hashCode());
		// 다른 주소값을 가지고 있음 == 다른 곳을 참조하고 있음
		// => 깊은 복사가 제대로 이루어져 배열을 수정할 때 서로 영향을 받지 않는다는 것을 유추 가능
		
	}

 

세 번째 방법

Arrays.copyOf(original, newLength);

복사본배열 = Arrays.copyOf(원본배열명, 복사할개수);

	public void method4() {
		
		// 3. Arrays 클래스의 copyOf 메소드를 호출하는 방법
		
		// 원본 배열
		int[] origin = {1, 2, 3, 4, 5};
		
		// 복사본 배열
		// Arrays 클래스의 copyOf 메소드 사용 방법
		// [ 표현법 ] 복사본배열 = Arrays.copyOf(원본배열명, 복사할개수);
		int[] copy = Arrays.copyOf(origin, 10); // 이때, copy배열의 크기 == 복사할 개수
		// 원본 배열보다 작거나 많아도 해당 메소드의 복사할개수가 우선됨!
		
		System.out.println("== 복사본 배열 출력 ==");
		for(int i = 0; i < copy.length; i++) {
			System.out.print(copy[i] + " ");
		}
		
		System.out.println("\n원본 배열의 해시코드값: " + origin.hashCode());
		System.out.println("복사본 배열의 해시코드값: " + copy.hashCode());
		// => 깊은 복사가 잘되었음
		
	}

주의할 점!

 

// 원본 배열 5개

int[] origin = {1, 2, 3, 4, 5}; 

 

//copy를 10개 하면

int[] copy = ArraycopyOf(origin, 10);

// 1 2 3 4 5 0 0 0 0 0

 

// copy를 3개 하면

int[] copy = ArraycopyOf(origin, 3);

// 1 2 3 

 

=> 즉, 크기를 신경 써야 함!

 

네 번째 방법

복사본배열명 = 원본배열명.clone();

	public void method5() {
		
		// 4. Clone 메소드를 호출하여 복사
		
		// 원본 배열
		int[] origin = {1, 2, 3, 4, 5};
		
		// 복사본 배열
		// clone 메소드 사용법
		// [ 표현법 ] 복사본배열명 = 원본배열명.clone();
		int[] copy = origin.clone(); // 별도의 옵션 존재하지 않음
		
		// 복사본 출력해 보기
		// [1, 2, 3, 4, 5] 형태로 출력하고 싶음!
		
		/*
		System.out.print("[");
		for(int i = 0; i < copy.length; i++) {
			
			// 내용물 출력
			
			if(i < copy.length - 1) { // 마지막 인덱스가 아닐 경우
				
				System.out.print(copy[i] + ", ");
			}
			
			else { // 마지막 인덱스일 경우
				System.out.println(copy[i]);
			}
			
		}
		
		System.out.print("]");
		*/
		
		System.out.println(Arrays.toString(copy));
		// Arrays.toString(출력하고자하는배열명);
		// => 앞과 뒤에 각각 [, ] , 내용물 사이에는 쉼표로 연이어져서 한 개의 문자열로 내보내 주는 메소드
		
		System.out.println("원본 배열의 해시코드값: " + origin.hashCode());
		System.out.println("복사본 배열의 해시코드값: " + copy.hashCode());
        // 깊은 복사가 잘 이루어졌다.
	}

 


배열 복사 한눈에 보기

(얕은 복사든 깊은 복사든 일단 원본 배열이 있어야 한다는 것은 동일! 당연함)

 

1) 얕은 복사

int[] copy = origin;

 

2) 깊은 복사

(1) int[] copy = new int[origin.length];

(2) int[] copy = new int[10]; //System.arraycopy는 배열의 범위를 넘으면 오류가 나기 때문에 넉넉하게 잡아 놓기

      System.arraycopy(원본배열명, 원본배열에서복사를시작할인덱스, 복사본배열명, 복사본배열에서복사를시작할인덱스, 복사할개수)

(3) int[] copy = Arrays.copyOf(origin, 10); // 이때 copy 배열의 크기 = 복사할 개수! 원본 배열보다 작거나 많아도 해당 메소드의 복사할개수가 우선됨

(4) int[] copy = origin.clone(); // 복사본배열명 = 원본배열명.clone(); 의 표현법을 따르되 별도의 옵션은 없음


 

 

 

저작자표시 (새창열림)
'📗 self-study/📗 KH정보교육원 당산지원' 카테고리의 다른 글
  • [Java] 06_객체(캡슐화, 클래스 실습, 필드, 접근 제한자)
  • [Java] 06_객체(개념과 추상화, 대입)
  • [Java] 배열 연습문제 정리
  • [Java] 04_제어문(분기문 -break문, continue문)
천재강쥐
천재강쥐
  • 천재강쥐
    디버거도 버거다
    천재강쥐
  • 전체
    오늘
    어제
    • Category (467)
      • 진짜 너무 궁금한데 이걸 나만 몰라...? (0)
      • 💾 Portfolio (2)
      • 🐤 CodingTest (28)
        • Java (20)
        • ᕕ(ꐦ°᷄д°᷅)ᕗ❌ (5)
      • 🚀 from error to study (142)
        • AI (1)
        • Cloud (2)
        • DB (12)
        • Front-End (16)
        • Github (14)
        • Java (39)
        • Mac (7)
        • Normal (29)
        • Server (22)
      • 📘 certificate (44)
        • 📘 리눅스마스터1급 (1)
        • 📘⭕️ 정보처리기사 (40)
        • 📘⭕️ SQLD (3)
      • 📗 self-study (234)
        • 📗 inflearn (35)
        • 📗 생활코딩 (8)
        • 📗 KH정보교육원 당산지원 (190)
      • 🎨 Scoop the others (0)
        • 📖 Peeking into other people.. (0)
        • 🇫🇷 (0)
        • 📘⭕️ 한국사능력검정시험 심화 (11)
        • 오블완 (4)
  • 인기 글

  • hELLO· Designed By정상우.v4.10.1
천재강쥐
[Java] 05_배열(Array)
상단으로

티스토리툴바