본문 바로가기

웹개발 수업/JAVA

[Day +9]배열2

210705 월

 

<배열>

1. 배열

 

4) 배열 복사

(1) 얕은 복사

: 객체의 주소 값만 가져와 참조형 변수에 저장하고 하나의 객체를 두 변수가 참조하는 것

 

(2) 깊은 복사

: 새로운 배열 객체를 생성하여 기존 배열의 데이터를 복사하는 것

package com.kh.array;

import java.util.Arrays;

public class B_ArrayCopy {

	//얕은 복사 : 배열의 주소만을 복사
	//깊은 복사 : 동일한 새로운 배열을 하나 생성해서 실제 내부 값들을 복사
	
	public void method1() {
		
		int[] origin = {1, 2, 3, 4, 5};
		
		// origin 배열을 copy로 복사
		int[] copy = origin;
		
		System.out.println("원본 배열 출력");
		for(int i = 0 ; i < origin.length ; i++) {
			System.out.print(origin[i] + " ");
		}
		System.out.println();
		
		System.out.println("복사본 배열 출력");
		for(int i = 0 ; i < copy.length; i++) {
			System.out.print(copy[i] + " ");
		}
		System.out.println();
		
		//복사 된 copy 배열의 2번 인덱스 값 변경
		copy[2] = 99; //=> 이것이 바로 변경 처리
		
		System.out.println("=====복사본 배열 값 변경 후 =====");
	
		
		System.out.println("원본 배열 출력");
		for(int i = 0 ; i < origin.length ; i++) {
			System.out.print(origin[i] + " ");
		}
		System.out.println();
		
		System.out.println("복사본 배열 출력");
		for(int i = 0 ; i < copy.length; i++) {
			System.out.print(copy[i] + " ");
		}
		System.out.println();
		
		/*답
		 * 원본 배열 출력
			1 2 3 4 5 
			복사본 배열 출력
			1 2 3 4 5 
			=====복사본 배열 값 변경 후 =====
			원본 배열 출력
			1 2 99 4 5 
			복사본 배열 출력
			1 2 99 4 5 
		 */
		
		
		//copy 인덱스 2번 값만 바꿨지만 원본과 복사본 값 모두 바뀌었다.
		//copy만 변경해도 origin 배열 값도 변경 되어 있음을 확인
		//그 이유는 origin과 copy가 같은 배열을 참조 하고 있기 때문(같은 주소값)
		System.out.println();
		
		System.out.println("origin의 주소값 : " + origin.hashCode());
		System.out.println("copy의 주소값 : " + copy.hashCode());
		
		//답
		//origin의 주소값 : 705927765
		//copy의 주소값 : 705927765
		//해쉬 코드가 같다 = 같은 것을 참조한다
	}
	
	//복사 된 새로운 배열을 만들기 위해서는 깊은 복사 필요
	public void method2() {
		//1. for문
		//	새로운 배열을 생성한 후 반복문을 통해 값을 대입
		int[] origin = {1, 2, 3, 4, 5};
		
		int[] copy = new int[5];
		//현재 copy는 비어있다, 현재는 0
		
		for(int i = 0 ; i < origin.length ; i++) {
			//반복문을 통해 origin에 있는 값들을 copy에 대입
			copy[i] = origin[i]; 
			//copy1번에 origin1번.. 이런식으로 복사해준 격
		}
			System.out.println("원본 배열 출력");
			for(int i = 0 ; i < origin.length ; i++) {
				System.out.print(origin[i] + " ");
			}
			System.out.println();
			
			System.out.println("복사본 배열 출력");
			for(int i = 0 ; i < copy.length; i++) {
				System.out.print(copy[i] + " ");
			}
			System.out.println();
			/*원본 배열 출력
			1 2 3 4 5 
			복사본 배열 출력
			1 2 3 4 5 */
			
			copy[2]=99;
			System.out.println("====copy[2]변경 후=====");
			
			System.out.println("원본 배열 출력");
			for(int i = 0 ; i < origin.length ; i++) {
				System.out.print(origin[i] + " ");
			}
			System.out.println();
			
			System.out.println("복사본 배열 출력");
			for(int i = 0 ; i < copy.length; i++) {
				System.out.print(copy[i] + " ");
			}
			System.out.println();
			
			/*====copy[2]변경 후=====
			원본 배열 출력
			1 2 3 4 5 
			복사본 배열 출력
			1 2 99 4 5 
			깊은 복사 시 복사본 배열만 99로 변경 된 것 확인 
			 */
			
			System.out.println();
			
			System.out.println("origin의 주소값 : " + origin.hashCode());
			System.out.println("copy의 주소값 : " + copy.hashCode());
			
			/*
			 * origin의 주소값 : 705927765
				copy의 주소값 : 366712642
				주소 값도 다르다
			 */
			
		} 
		
		 public void method3() {
			 //2. System 클래스의 arraycopy 메소드를 이용한 복사
			 
		int[] origin = {1, 2, 3, 4, 5};
		
		int[] copy = new int[10];
		
		/* System.arraycopy(원본배열(src), 복사 시작 인덱스(srcPos) => 어디서부터 할거냐
		, 복사본 배열(dest), 복사본 배열에서 복사가 시작될 위치(destPos), 
        복사하고자 하는 길이(length ); */
		System.arraycopy(origin, 0, copy, 2, origin.length);
		//origin의 0부터 복사해서 copy의 2번에 가져다가 붙여 넣어라
		
		System.out.println("원본 배열 출력");
		for(int i = 0 ; i < origin.length ; i++) {
			System.out.print(origin[i] + " ");
		}
		System.out.println();
		
		System.out.println("복사본 배열 출력");
		for(int i = 0 ; i < copy.length; i++) {
			System.out.print(copy[i] + " ");
			
			/*답
			 * 원본 배열 출력
			1 2 3 4 5 
			복사본 배열 출력
			0 0 1 2 3 4 5 0 0 0 
			 */
			
			
		
		// 다른 주소 값을 가지므로 한 배열의 값 변경 시 다른 배열 영향 받지 않음(깊은 복사)
		}
		System.out.println();
		
		System.out.println("origin의 길이 : " + origin.length);
		System.out.println("copy의 길이 : " + copy.length);
		System.out.println("origin의 주소값 : " + origin.hashCode());
		System.out.println("copy의 주소값 : " + copy.hashCode());
		
		/*답
		 * origin의 길이 : 5
		copy의 길이 : 10
		origin의 주소값 : 705927765
		copy의 주소값 : 366712642

		 */
		//다른 주소 값을 가지므로 한 배열의 값 변경시 다른 배열 영향 받지 않음(깊은 복사)
		//System.arraycopy 메소드를 통해 복사 위치, 복사 개수 등 지정 가능
		//물론 for문의 인덱스를 조절하여 같은 기능 구현 가능함
		
		 }
		 
		public void method4() {
			//3. Arrays 클래스에서 제공하는 copyOf 메소드 사용
			//Arrays 클래스는 배열을 이용할 때 유용한 메소드를 모아놓은 클래스
			
			int[] origin = {1, 2, 3, 4, 5};
			
			
			//복사본 배열 = Arrays.copyOf(원본 배열, 복사할 길이);
			int[] copy = Arrays.copyOf(origin,  3);
			//복사할 길이에 입력한 크기만큼 새로운 배열이 할당 되고
			//원본 배열의 첫 번째 인덱스부터 가능한 길이만큼 복사해옴
			
			//java api 8 (해당 메소드 shift + f2)
			
			System.out.println("원본 배열 출력");
			for(int i = 0 ; i < origin.length ; i++) {
				System.out.print(origin[i] + " ");
			}
			System.out.println();
			
			System.out.println("복사본 배열 출력");
			for(int i = 0 ; i < copy.length; i++) {
				System.out.print(copy[i] + " ");
			/*
			 * 원본 배열 출력
			1 2 3 4 5 
			복사본 배열 출력
			1 2 3 4 5 
			
			=> copy의 숫자를 5에서 10으로 변경했을 때
			복사본 배열 출력
			1 2 3 4 5 0 0 0 0 0 
			
			=> copy의 숫자를 10에서 3으로 변경했을 때
			복사본 배열 출력
			1 2 3 
			 */
			
		}
		}
		
		public void method5() {
			//4. clone 메소드를 이용한 복사
			// 시작 인덱스를 지정할 수 없으며 원본 배열 통채로 복사해 새로운 배열 할당
			
		int[] origin = {1, 2, 3, 4, 5};
		int[] copy = origin.clone();
		
		System.out.println("원본 배열 출력");
		for(int i = 0 ; i < origin.length ; i++) {
			System.out.print(origin[i] + " ");
		}
		System.out.println();
		
		System.out.println("복사본 배열 출력");
		for(int i = 0 ; i < copy.length; i++) {
			System.out.print(copy[i] + " ");
		
			/*원본 배열 출력
			1 2 3 4 5 
			복사본 배열 출력
			1 2 3 4 5*/ 
			
		
		}
		System.out.println("origin의 주소값 : " + origin.hashCode());
		System.out.println("copy의 주소값 : " + copy.hashCode());
		
		/*
		 * 1 2 3 4 5 origin의 주소값 : 705927765
			copy의 주소값 : 366712642
		 */
		
		//얕은 복사와는 다르다. 새로운 공간 출력. 
		

		} 
		
		
		
	}
package com.kh.array;

import java.util.Arrays;

public class C_ArraySort {

	//배열 정렬
	public void method1() {
		//배열을 정렬하기에 앞에서 변수를 가지고 값을 변경해보자
		
		//우선 두 개의 변수의 값을 서로 변경하는 방법
		int num1 = 20;
		int num2 = 10;
		
		System.out.println("===변경 전===");
		System.out.println("num1 : " + num1);
		System.out.println("num2 : " + num2);
		
		// num1과 num2의 값을 서로 바꾼다고 생각해보자.
		
		//num1 = num2;
		//num2 = num1;
		
		//=> 이렇게 하면 num2 값이 num1으로 가고 num1값이 다시 num2로 가기 때문에 ㅇ나됨
		//따라서 값을 임시로 보관할 새로운 변수를 만들어 값을 이동 시켜야 함
		
		//System.out.println("===변경 후===");
		//System.out.println("num1 : " + num1);
		//System.out.println("num2 : " + num2);
		
		
		/*===변경 전===
		num1 : 20
		num2 : 10
		===변경 후===
		num1 : 10
		num2 : 10*/
		
		int temp;
		temp = num1;
		num1 = num2;
		num2 = temp;
		
		System.out.println("===변경 후===");
		System.out.println("num1 : " + num1);
		System.out.println("num2 : " + num2);
		
		/*===변경 후===
		num1 : 10
		num2 : 20*/

		
	}
	
	public void method2() {
		//배열도 동일하게 위치 변경 가능
		int[] arr = {2, 1, 3}; // 하나씩 왼쪽으로 밀고 싶다 => 똑같이 임시 변수를 만들자
		
		int temp = arr[0];
		arr[0] = arr[1];
		arr[1] = arr[2];
		arr[2] = temp;
		
		for(int i = 0 ; i < arr.length ; i++) {
			System.out.println("arr[" + i + "] : " + arr[i]);
		}
		/* 답
		 * arr[0] : 1
			arr[1] : 3
			arr[2] : 2
		*/		
	}
	
	public void method3() {
		//삽입 정령(insertion sort)
		//배열의 n번 인덱스 값을 0번 ~ n-1 번 인덱스까지 비교
		
		//비교 주체        비교 대상
		// i = 1일 때 j = 0 ~ 0
		// i = 2일 때 j = 0 ~ 1
		// i = 3일 때 j = 0 ~ 2
		// i = 4일 때 j = 0 ~ 3
		
		// i = 1부터 마지막까지 반복할 때 => 외부 for문
		// j = 0부터 i-1까지 반복 => 내부 for문
		
		int[] arr = {2, 5, 4, 1, 3};
		
		
		for(int i = 1 ; i < arr.length ; i++){
			//인덱스가 증가할 때마다 처음부터 해당 인덱스 전까지 값을 비교하는 반복문
			for(int j = 0 ; j < i ; j++) {
				System.out.println("현재 인덱스 위치 : " + i + ", " + j);
			
			if(arr[i] < arr[j]) { //부호 반대로 할 경우 내림차순
				System.out.println("====교환 발생====");
				int temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
				
			}
			System.out.println(i + "회전 : " + Arrays.toString(arr));
			}
			
		}
		
		System.out.println("================");
		System.out.println("최종 결과 : " + Arrays.toString(arr));
		
		
		/* 현재 인덱스 위치 : 1, 0
		1회전 : [2, 5, 4, 1, 3]
		현재 인덱스 위치 : 2, 0
		2회전 : [2, 5, 4, 1, 3]
		현재 인덱스 위치 : 2, 1
		====교환 발생====
		2회전 : [2, 4, 5, 1, 3]
		현재 인덱스 위치 : 3, 0
		====교환 발생====
		3회전 : [1, 4, 5, 2, 3]
		현재 인덱스 위치 : 3, 1
		====교환 발생====
		3회전 : [1, 2, 5, 4, 3]
		현재 인덱스 위치 : 3, 2
		====교환 발생====
		3회전 : [1, 2, 4, 5, 3]
		현재 인덱스 위치 : 4, 0
		4회전 : [1, 2, 4, 5, 3]
		현재 인덱스 위치 : 4, 1
		4회전 : [1, 2, 4, 5, 3]
		현재 인덱스 위치 : 4, 2
		====교환 발생====
		4회전 : [1, 2, 3, 5, 4]
		현재 인덱스 위치 : 4, 3
		====교환 발생====
		4회전 : [1, 2, 3, 4, 5]
		================
		최종 결과 : [1, 2, 3, 4, 5]*/
		
		
	}
	
	public void method4() {
		
		int[] arr = {2, 5, 4, 1, 3};
	
		Arrays.sort(arr); //이것을 이용하면 바로 오름차순 정렬이 된다.
		//Arrays.sort(arr, 0, 3);//fromIndex, toIndex
		//0번 인덱스부터 3번 인덱스 저까지 정렬 : 0 ~ 2 정렬, 즉 부분 정렬
		//하나의 이름을 가진 메소드가 매개 변수 타입(int, double, char...)과 개수에 따라 다르게 동작
		//내림차순 정렬은 Comparator 객체 전달이 필요하다. => 나중에 학습할 예정
		System.out.println(Arrays.toString(arr));
		
		int[] copy = new int[arr.length];
		for(int i = 0 ; i < copy.length ; i++) {
			copy[i] = arr[copy.length - 1 - i];
			//arr는 인덱스가 4, 3, 2, 1, 0 값으로 들어가게 
			//copy는 0, 1, 2, 3, 4로 올라가게 해준 것.
			//오름차순을 내림차순으로 바꾼 것 뿐 어렵지않죠
		}
		
		
	
			
		//답 
		//[1, 2, 3, 4, 5]
		
		//내림차순 결과
				System.out.println(Arrays.toString(copy));
				
		//답
		//[5, 4, 3, 2, 1]


	}
	
	public void method5() {
		int[] arr = {2, 5, 4, 1, 3};
		
		
		for(int i = 1 ; i < arr.length ; i++){
			//인덱스가 증가할 때마다 처음부터 해당 인덱스 전까지 값을 비교하는 반복문
			for(int j = 0 ; j < i ; j++) {
				
			if(arr[i] < arr[j]) { //부호 반대로 할 경우 내림차순
				int temp = arr[i];
				arr[i] = arr[j];
				arr[j] = temp;
				System.out.println("최종 결과 : " + Arrays.toString(arr));
				
			}
		
	}
	}
	
}
}
package com.kh.array;

import java.util.Arrays;
import java.util.Scanner;

public class D_Overlap {
	
	public void method1() {
		//사용자에게 5개의 값을 입력 받아 배열에 저장
		//단, 중복 값은 허용하지 않음
		int[] arr= new int[5];
		Scanner sc = new Scanner(System.in);
		
		for(int i = 0; i < arr.length ; i++) {
			
			System.out.print(i + "번째 정수 값 : ");
			arr[i] = sc.nextInt();
			
		//중복 여부 검사 반복문
		for(int j = 0 ; j < i ; j++) {
			if(arr[i] == arr[j]) { //중복 값이 존재할 경우
				System.out.println("중복 값이 존재합니다. 다시 입력해주세요");
				i--; //외부 for문의 i++과 상쇄 
                => 중복이 발생했던 인덱스를 다시 입력 받게 함
				break; 
                // 중복이 발생한 시점에서 더 이상 체크할 필요가 없으므로 
                //중복 검사 반복문 탈출
			}
		}
			
		}
		
		System.out.println(Arrays.toString(arr));
		
	}
	
	public void method2() {
		//1~10 사이의 난수를 중복 없이 발생시켜 배열에 담기
		int[] arr = new int[5];
		
		for(int i = 0 ; i < arr.length ; i++) {
			arr[i] = (int)(Math.random() * 10 + 1);
			
		 //중복 체크 반복문 만들기
			for(int j = 0 ; j < i ; j++) {
				if(arr[i] == arr[j]) {
					System.out.println(j + "번째와 " + i + "번째 : " + arr[i] + "중복");
					i--;
					break;
				}
			}
			
		}
		
		System.out.println(Arrays.toString(arr));
				//로또 번호 당첨기 만들 수 있다 ㅎㅎ
		
		/*
		 * 0번째와 3번째 : 3중복
		[3, 10, 7, 5, 1]
		 */
	}
	
	
}
package com.kh.arrayrun;

import com.kh.array.A_Array;
import com.kh.array.B_ArrayCopy;
import com.kh.array.C_ArraySort;
import com.kh.array.D_Overlap;

public class ArrayRun {

	public static void main(String[] args) {
		
		//A_Array a = new A_Array();
		//a.method9();
		
		//B_ArrayCopy b = new B_ArrayCopy();
		//b.method4();
		
		//C_ArraySort c = new C_ArraySort();
		//c.method5();
		
		D_Overlap d = new D_Overlap();
		d.method2();

	}

}