package com.test.java;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Scanner;
public class Ex27_Array {
public static void main(String[] args) {
// 배열, Array
// - 자료구조 > 데이터 저장하는 물리적인 구조
// - 데이터의 집합 > 변수들을 모아놓은 집합
// - 같은 자료형을 저장하는 데이터의 집합
// m1();
// m2();
// m3();
// m4();
// m5();
// m6();
// m7();
// m8();
// m9();
// m10();
// m11();
// m12();
// m13(); // 배열 요소 삽입
// m14(); // 배열 요소 삭제
// m15();
// m16();
// m17();
// m18();
m19();
// 정렬
// - 크기 비교 후 > 재배치
// 1. 오름차순
// a. 숫자: 작은수 > 큰수
// b. 문자열: 문자코드값 순
// c. 날짜시간: 과거 > 미래
// 2. 내림차순
// a. 숫자: 큰수 > 작은수
// b. 문자열 : 문자코드값 역순
// c. 날짜시간: 미래 > 과거
// 정렬 구현
// 1. 직접 구현 > 정렬 알고리즘
// 2. JDK 구현된 기능 (!)
// 버블 정렬 + swap
// swap > 두 공간의 데이터를 서로 바꾸는 작업
int a = 10;
int b = 5;
int temp; // 바꾸기 위한 빈컵
temp = a; // a 는 비어있다
a = b; // b가 a로 옮겨지다
b = temp;
System.out.println("a: " + a);
System.out.println("b: " + b);
// 1사이클 n - 1 개 비교
// 2사이클 n - 2 개 비교
// ...
int[] nums = { 5, 3, 1, 4, 2 };
System.out.println(Arrays.toString(nums));
for (int i=0; i<nums.length-1; i++) {// 사이클 (0, 1, 2 , 3)
// 실제비교는여기부터
for (int j=0; j<nums.length-1-i; j++) {
// 오름차순
if (nums[j] > nums[j+1]) {
temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
// 내림차순 if (nums[j] < nums[j+1]) {
}
}
}
System.out.println(Arrays.toString(nums));
// String name1 = "홍길동";
// String name2 = "아무개";
// 문자코드값 비교
// 첫번째 글자
// System.out.println(name1.compareTo(name2));
// 두 글자의 문자코드값 차이 = 4361
// System.out.println((int)'홍'); // 문자코드값 문자가 뒤에 있을 수록 크니깐....
// System.out.println((int)'아'); // 우리는 어떤 것이 앞에 있는 글자이고 뒤에 있는 글자인 것인지 알면 된다...
String[] names = { "홍길동", "아무개", "테스트", "유재석", "강아지", "고양이", "도깨비", "박명수", "조세호", "병아리" };
for (int i=0; i<names.length-1; i++) {
for (int j=0; j<names.length-1-i; j++) {
// 오름차순, 가나다순정렬
if (names[j].compareTo(names[j+1])>0) {
String temp2 = names[j];
names[j] = names[j+1];
names[j+1] = temp2;
}
}
}
System.out.println(Arrays.toString(names)); //날짜 시간도 가능
// 49 번 for 문 (공백 for 문 + 별 for 문)
// 52 번 문자코드로 만듦, 증가, 감소순
// 53 번 2 x 1 = 2 3 x 1 = 3 4 x 1 = 4 5 x 1 = 5 한줄을 먼저 찍은 것, 단이 먼저가 아닌......? 이중 for 문 2번 혹은 삼중 for 문 1번 사용
// 54 번 2 ~ 10 까지 돌리고 11/2, 11/3..... 나머지 0이면 약수??????????????????????
// 57 번 단일 for 문이나 이중 for 문 사용
// 59, 60 번 수열문제..
}// main
private static void m19() {
int[][] nums = new int[5][5];
int n = 1;
// 2차원 배열 값 넣기
for (int i=4; i>=0; i--) {
for (int j=4; j>=0; j--) { // 4 3 2 1 0
nums[i][j] = n; //접근하는 순서대로 1~ 넣음
n++;
}
System.out.println(
);
}
for (int i=0; i<5; i++) {
for (int j=0; j<5; j++) {
System.out.printf("%3d", nums[i][j]);
}
}
}
private static void m18() {
//****** 배열의 길이는 불변이다.
// - 한번 만들어진 배열의 방은 더 늘리거나 삭제할 수 없다.
//int[] kor = new int[300]; //정적 할당 , 최대수, 여유치
// 길이를 상수가 아닌 변수로 쓸 수 있으나, 이때도 X
Scanner scan = new Scanner(System.in);
System.out.print("학생수: ");
int length = scan.nextInt();
// int length = 3;
int[] kor = new int[length]; // 동적 할당 , 사용자가 입력한 값으로 초기화시킬 수 있으므로 프로그램 동작중에 할당
}
private static void m17() {
for (int i=0; i<10; i++) {
System.out.println((int)(Math.random()* 100) + 1 ); // 원래 난수는 실수 ,
}
}
private static void m16() {
// 초기화 리스트
int[] nums1 = { 10, 20, 30 };
int[][] nums2 =
{
{ 10, 20, 30 },
{ 40, 50, 60 }
};
int[][][] nums3 =
{
{
{ 10, 20, 30 },
{ 40, 50, 60 }
},
{
{ 70, 80, 90 },
{100, 110, 120 }
}
};
// Jagged Array, 비정형 배열, 불규칙 배열
int[][] nums4 = new int[3][4]; //안됨
int[][] nums5 =
{
{ 10, 20, 30 },
{ 40, 50 },
{ 60, 70, 80, 90 }
};
// Jagged Array 탐색
for (int i=0; i<nums5.length; i++) {
for (int j=0; j<nums5[i].length; j++) { // 고정이 아니므로 i
System.out.printf("%5d", nums5[i][j]);
}
System.out.println();
}
}
private static void m15() {
// 배열의 차원
// - 1차원 배열(인덱스를 하나 써서), 2차원 배열(y좌표부터) , 3차원 배열(겹쳐서..)..
// 1차원 배열
int[] nums1 = new int[3];
nums1[0] = 10;
nums1[1] = 20;
nums1[2] = 30;
System.out.println(Arrays.toString(nums1));
// 2차원 배열
int[][] nums2 = new int[2][3]; // 2차원 - 2, 3차원 - 3
nums2[0][0] = 10;
nums2[0][1] = 20;
nums2[0][2] = 30; // 1층 끝
nums2[1][0] = 10;
nums2[1][1] = 20;
nums2[1][2] = 30; // 2층 끝
// nums2 자료형? > int[][] > int 2차원배열이다
// nums2[0] 자료형 ? > int[] > int 1차원 배열
// nums2[0][0] 자료형? > int
nums2[0][1] = 20;
System.out.println(nums2.length); // 2
System.out.println(nums2[0].length); // 3
System.out.println(nums2[0][0]); // 10
System.out.println(Arrays.toString(nums2));
System.out.println(Arrays.deepToString(nums2));
//System.out.println(nums2.length); // 2 겉에보이는구조때문에.
//2차원 배열 탐색
// 2중 for 문의 i와 j
for (int i=0; i<nums2.length; i++) { // 바깥
for (int j=0; j<nums2[0].length; j++) { // 한바퀴를 돌면 한층
System.out.println(nums2[i][j] + "\t");
}
System.out.println(); // 층이 바뀐다는 의미로 엔터
}
System.out.println();
//3차원 배열
int[][][] nums3 = new int[2][3][3];
nums3[0][0][0] = 10;
nums3[0][0][1] = 20;
nums3[0][0][2] = 30;
nums3[0][1][0] = 40;
nums3[0][1][1] = 50;
nums3[0][1][2] = 60;
nums3[1][0][0] = 70;
nums3[1][0][1] = 80;
nums3[1][0][2] = 90;
nums3[1][1][0] = 100;
nums3[1][1][1] = 110;
nums3[1][1][2] = 120;
for (int i=0; i<nums3.length; i++) {
for (int j=0; j<nums3[0].length; j++) {
for (int k=0; k<nums3[0][0].length; k++) {
System.out.printf("%5d", nums3[i][j][k]);
}
System.out.println();
}
System.out.println();
}
}
private static void m14() {
// 배열 요소 삭제(Deletion)
// 삽입의 역방향 (오른쪽에서 왼쪽으로 복사)
// 마지막 비워져 있으면 0으로 채워넣음
// - Left Shift > 왼쪽으로 한칸씩 이동했다.
// - *** 삭제 이후의 요소들이 인덱스가 변경된다.
int[] nums = { 1, 2, 3, 4, 5 };
int index = 1;
System.out.println(Arrays.toString(nums));
// 필요한 인덱스 1, 2, 3
for (int i=index; i<=nums.length-2; i++) {
nums[i] = nums[i+1];
}
nums[nums.length-1] = 0; // 마지막 방
System.out.println(Arrays.toString(nums));
}
private static void m13() {
// 배열 조작
// - 삽입, 삭제
// - 비용 발생
// 삽입 마지막요소 사라질수도 있음
// 오른쪽부터 한칸씩 복사 후 안전한 상태에서 삽입
// 중간에 삭제하면 앞으로 간다
// 중요
// 배열 삽입(Insertion)
// - Right Shift > 오른쪽으로 한칸씩 이동했다.
// - *** 삽입 이후의 요소들이 인덱스가 변경된다. (값이 변한다. 중요)
int[] nums = { 1, 2, 3, 4, 5 };
int index = 1;
int value = 9; // 삽입할 값
System.out.println("nums[0] = " + nums[0]);
System.out.println("nums[3] = " + nums[3]);
//초기상태
System.out.println(Arrays.toString(nums));
// 한칸씩 복사
for (int i=nums.length-2; i>=index; i--) {
System.out.println(i);
nums[i+1] = nums[i];
System.out.println(Arrays.toString(nums));
}
// 삽입
nums[index] = value;
System.out.println(Arrays.toString(nums));
System.out.println("nums[0] = " + nums[0]);
System.out.println("nums[3] = " + nums[3]);
}
private static void m12() {
int[] nums = { 5, 3, 1, 4, 2 };
String[] names = { "홍길동", "아무개", "테스트", "유재석", "강아지", "고양이", "도깨비", "박명수", "조세호", "병아리" };
// sort(Object) 문자
// Quick Sort
Arrays.sort(nums);
System.out.println(Arrays.toString(nums));
Arrays.sort(names);
System.out.println(Arrays.toString(names));
}
private static void m11() {
// 배열 초기화 리스트
int[] nums1 = new int[5];
//값이 불규칙
nums1[0] = 95;
nums1[1] = 88;
nums1[2] = 67;
nums1[3] = 89;
nums1[4] = 64;
System.out.println(Arrays.toString(nums1));
int[] nums2 = new int[] {95, 88, 67, 89, 64}; // 영역의 블럭이 아니므로 반드시 뒤에 세미콜론이 있어야 한다
System.out.println(Arrays.toString(nums2));
// 초기화 리스트
int[] nums3 = {95, 88, 67, 89, 64};
System.out.println(Arrays.toString(nums3));
String[] names1 = new String[3];
names1[0] = "홍길동";
names1[1] = "임꺽정";
names1[2] = "도깨비";
String[] names2 = {"홍길동", "임꺽정", "도깨비"};
System.out.println(Arrays.toString(names1));
System.out.println(Arrays.toString(names2));
}
private static void m10() {
// 배열 자동 초기화
// - 배열은 생성 직후 모든 요소(방)가 초기화가 된다.
// 초기화 규칙
// 1. 정수배열 > 0
// 2. 실수배열 > 0.0
// 3. 문자열 > \0 (\u0000)
// 4. 논리배열 > false
// 5. 참조형배열 > null
int[] list1 = new int[3];
System.out.println(Arrays.toString(list1));
byte[] list2 = new byte[3];
System.out.println(Arrays.toString(list2));
double[] list3 = new double[3];
System.out.println(Arrays.toString(list3));
char[] list4 = new char[3];
System.out.println(Arrays.toString(list4));
boolean[] list5 = new boolean[3];
System.out.println(Arrays.toString(list5));
String[] list6 = new String[3];
System.out.println(Arrays.toString(list6));
}
private static void m9() {
// Arrays 클래스
// - 유틸리티 클래스
// - 배열과 관련된 여러가지 기능을 구현한 클래스
// - 배열을 조작하는 편리한 기능을 제공하는 역할
int[] nums = new int[3];
nums[0] = 10;
nums[1] = 20;
nums[2] = 30;
// 배열의 상태를 확인?
// [I@2ff4acd0
// [I > int[]
// @
// 2ff4acd0 > 메모리 주소
System.out.println(nums); // 쓸모없음
// 직접 출력
printArray(nums); //메서드로 만듦
// 하지만 만들지 않아도 자바가 제공
System.out.println(Arrays.toString(nums)); // dump (덤프) 메서드 , 배열을 문자열로 만들어주겠다는..
// *** C계열의 언어들은 범위를 나타낼때
// - 시작위치(inclusive) ~ 끝위치(exclusive)
// 깊은 복사
int [] copy; // 복사본 배열 변수 먼저 만들기
copy = Arrays.copyOfRange(nums, 0, nums.length); // 몇번째 방 부터 몇번째 방까지 복사할래? length만 적는 이유, 끝위치 포함 안시켜서
nums[0] = 100;
System.out.println(Arrays.toString(nums));
System.out.println(Arrays.toString(copy));
}
public static void printArray(int[] nums) {
for (int i=0; i<nums.length; i++) {
System.out.printf
("%3d", nums[i]);
} System.out.println();
}
private static void m8() {
// 배열 복사
// 1. 얕은 복사, Shallow Copy
// - 주소값 복사
// - Side Effect 발생
// 2. 깊은 복사, Deep Copy
// - 실제 배열 복사
// - Side Effect 발생 안함
int[] nums = new int[3];
nums[0] = 10;
nums[1] = 20;
nums[2] = 30;
int[] copy = new int[3]; // 직접 방을 만든다..
for (int i=0; i<nums.length; i++) {
//방과 방끼리의 복사 > 요소끼리의 복사
//int = int (값형끼리의 복사)
copy[i] = nums[i];
}
nums[0] = 100;
System.out.println(copy[0]); // 안변함..
}
private static void m7() {
int a = 10; //원본
changValue(a);
System.out.println(a); // 지역변수이고 값형변수라 20이 아니다
int[] nums = new int [3];
nums[0] = 10;
nums[1] = 20;
nums[2] = 30;
changeArray(nums);
System.out.println(nums[0]); // 참조형이므로 지역변수의 생명주기랑 상관없이 바뀌어 있음
}
private static void changeArray(int[] nums) { // 실인자 가인자 복사,
nums[0] =123;
System.out.println(nums[0]);
//참조형을 사용하면, 굳이 return 값을 사용하지 않아도 돌려준다
}
private static void changValue(int a) {
a = 20; //수정
System.out.println(a);
}
private static void m6() {
// *** 반드시 이해해야 함
// 배열 복사(= 참조형 복사)
//값형 복사
int a = 10;
int b;
b = a;
// 값형 > 원본을 수정해도 복사본에 영향을 주지 않는다. > Side effect 발생하지 않는다.
a = 20; // 원본 수정
System.out.println("a: " + a);
System.out.println("b: " + b); // 안바뀜 , 복사를 한것이지 같은 아이가 아니므로...
System.out.println();
int[] nums = new int[3];
nums[0] = 10;
nums[1] = 20;
nums[2] = 30;
int[] copy;
// int[] 가 자료형임 읽을때 int 배열이라고 읽음
// int[] = int[]
copy = nums; // 참조가 늘어난 것... 모든 참조형은 실제 데이터 복사가 아닌 주소값을 복사한다.
System.out.println(copy[0]);
System.out.println(copy[1]);
System.out.println(copy[2]);
// 원본을 수정하면 복사본도 수정된다.
// 복사본을 수정하면 원본도 수정된다.
// > Side effect가 발생한다.
nums[0] = 100; //수정
System.out.println(copy[0]); // 바뀜..!
System.out.println(copy[1]);
System.out.println(copy[2]);
copy[1] = 200; //반대로 수정
System.out.println(nums[1]);
// 문자열 빼고 모든 참조형의 특징이다.
// 문자열은 소속은 참조형인데, 특성은 값형을 많이 가지고 있음
}
private static void m5() {
// 값형 vs 참조형
// - 값형 > 변수에 데이터를 직접 저장
// - 참조형 > 데이터는 따로 생성 + 변수에 메모리 주소값 저장
// *** 원인
// - 데이터 크기가 일정 > 값형
// - 데이터 크기가 일정하지 않음 > 참조형
// - *** 변수만 보고 데이터의 길이를 추측 가능 > 값형
// - *** 변수만 보고 데이터의 길이를 추측 불가능 > 참조형
int a1 = 10;
// a1 의 메모리(공간) 크기? 4byte
int a2 = 2000000000;
// a2 의 메모리 크기? 4byte
String s1 = "홍길동";
// s1의 메모리 크기? 6byte (heap 위치, 2 * 3byte) / 참조형의 크기? stack 위치
// Stack 은 우리가 직접적으로 접근할 수 있으나, Heap 은 불가
String s2 = "안녕하세요";
// s2의 메모리 크기? 10byte
int[] nums1 = new int[3];
// 12byte
int[] nums2 = new int[5]
// 20byte
}
private static void m4() {
// 각 자료형 > 배열
// 정수 배열(byte, short, int, long)
byte[] list1 = new byte[5];
list1[0] = 10;
System.out.println(list1[0]);
// 실수 배열(float, double)
double[] list2 = new double[5];
list2[0] = 3.14;
System.out.println(list2[0]);
// 문자 배열(char) == String (문자열)
char[] list3 = new char[5];
list3[0] = 'A';
System.out.println(list3[0]);
// 논리 배열(boolean)
boolean[] list4 = new boolean[5];
list4[0] = true;
System.out.println(list4[0]);
// 참조형 배열
String[] list5 = new String[5];
list5[0] = "홍길동";
System.out.println(list5[0]);
Calendar c1 = Calendar.getInstance();
// 변수를 만들 수 있는 모든 자료형은 배열도 만들 수 있다
Calendar[] list6 = new Calendar[5];
list6[0] = Calendar.getInstance(); //Calendar.getInstance(); 도 해야 현재 시간이 들어간다. 안넣으면 null 값이없음
System.out.println(list6[0]);
}
private static void m3() {
//참조형의 특징
// - 모든 참조형들은 공간을 초기화하지 않아도 자동으로 초기화가 된다. (값형은 X)
// 예) System.out.println(num); 에러남
int[] nums = new int[10];
nums[0] = 10;
nums[1] = 20;
nums[2] = 30;
System.out.println(nums[0]);
System.out.println(nums[1]);
System.out.println(nums[2]);
System.out.println(nums[3]); // 0이 들어 있는 이유, 참조형의 특징 때문에..
// 배열의 길이 = 10
// 첨자의 범위 = 0 ~ 9
// 첨자의 범위 = 0 ~ 길이-1
// ArrayIndexOutOfBoundsException
// Index 10 out of bounds for length 10
// System.out.println(nums[10]); // 최대방의 길이가 9, 존재하지 않는 방번호 - 에러
// 배열 탐색 > for문 사용
for (int i=0; i<nums.length; i++) {
System.out.printf("nums[%d] = %d\n", i, nums[i]);
} // 전형적인 배열을 탐색할때 쓰는 for
// 배열은 모든 자료형으로 만들 수 있다.
}
private static void m2() {
// 요구사항] 학생 3명 > 국어 점수 > 총점, 평균
// 추가사항] 학생 수 증가 > 300명
// 배열은 참조형이다
// 배열 선언하기
// - 자료형 [] 변수명 = new 자료형 [길이];
// - 배열타입 배열명 = new 배열타입 [배열의길이];
int [] kors = new int[3]; // 왼쪽 : kors 은 Stack에, Heap 주소값 저장, 오른쪽 : heap 에 만들어지며, 연속으로 3칸, 4byte 씩 12byte
// 배열은 변수를 한꺼번에 만드는 일
// 배열의 index (첨자) : 각각 방의 번호
// 배열의 요소 element : 각각의 방
// 배열의 방(요소, Element)에 접근 > 방 번호(첨자, Index) 사용
// 배열의 길이 = 방의 갯수
// 같은 성질의 같은 자료형일 때 배열을 만든다.
kors [0] = 100; // 방 3개 중 1번째 방
kors [1] = 90;
kors [2] = 80;
// int total = kors[0] + kors[1] + kors[2];
int total = 0;
for (int i=0; i<kors.length; i++) {// 루프변수를 통해 모든 배열의 방번호를 얻을 수 있게 됨
total += kors[i];
}
double avg = (double)total / kors.length; // 속성, 필드, 프로퍼티
System.out.printf("총점: %d점, 평균 %.1f점\n", total, avg);
}
private static void m1() {
// 요구사항] 학생 3명 > 국어 점수 > 총점, 평균
// 추가사항] 학생수 증가 > 300명
int kor1;
int kor2;
int kor3;
// + 297 추가 선언
kor1 = 100;
kor2 = 90;
kor3 = 80;
// + 297 초기화
int total = kor1 + kor2 + kor3; // + kor4 + kor5 + ... + kor300
double avg = total / 3.0; // 3.0 > 300.0
System.out.printf("총점: %d점, 평균 %.1f점\n", total, avg);
}
}