반복적인 코드를 간단하게 표현하기 위해 만든 것!
-> 연속된 공간에 값을 나열시키고, 각 값에 인덱스를 부여해 놓는 자료 구조! (색인 배열)
-> 인덱스는 대괄호 []와 함께 사용하여 각 항목의 값을 읽거나 사용하는데 사용!
-> 힙 영역에 생성되고 배열 변수는 힙 영역의 배열 주소를 저장
-> 참조할 변수가 없을 경우 변수를 null로 초기화 하기
(int 형태의 변수에 초기값을 0으로 주는 것과 동일한 원리)
1. 타입[] 변수; -> JAVA에서는 이 방식을 사용함!
2. 타입 변수[]; -> C언어에서 주로 사용
-> 배열에 저장될 값의 목록이 있다면 간단하게 배열을 생성할 수 있음
-> 형태
타입[] 변수 = {값0, 값1, 값2, ...}; -> 배열 선언 및 초기화!
-> 위와 같은 형태를 배열의 암시적 표현이라고 함
-> 만약 배열 선언과 값을 대입하는 시점이 다를 경우 new 연산자를 이용해 배열 값을 넣어주기
-> 형태
변수 = new 타입[] {값0, 값1, 값2, ...};
-> 배열 생성 후 배열 참조 변수에 대입!
-> 변수 = {값0, 값1, 값2, ...}; 와 같이 new 연산자 없이 배열 값 넣는 것은 불가!
package ch05.sec06;
public class ArrayExam1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] team = { "SSG", "LG", "키움", "두산" };
// 배열을 선언 및 초기화 작업
System.out.println("team[0]: " + team[0]); // SSG
System.out.println("team[1]: " + team[1]); // LG
System.out.println("team[2]: " + team[2]); // 키움
System.out.println("team[3]: " + team[3]); // 두산
//배열 안의 있는 값들을 모두 출력
team[0] = "랜더스"; // 0번째 배열의 문자열을 바꿈
System.out.println("team[0]: " + team[0]); // 랜더스
for(int i=0;i<team.length;i++) {
System.out.println("team[" + i + "]: " + team[i]);
}
// team 배열의 길이만큼 값을 출력하기!
}
}
package ch05.sec06;
public class ArrayExam2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] scores = { 92, 86, 96, 88, 94 };
// scores 라는 배열변수에 값을 넣음
int sum1 = 0;
int sum2 = 0;
// 증감연산을 할 것이기 때문에 초기값을 설정하기
for(int i=0;i<scores.length;i++) {
sum1 += scores[i];
}
// scores 배열의 길이만큼 실행하기!
// 점수의 합계를 구하는 식
for(var score : scores) {
sum2 += score;
}
// score라는 임의의 변수를 줌
// scores라는 배열의 값을 순서대로 score에 집어넣음
// var : 자동적으로 타입을 파악하는 구문
// 점수의 합계를 구하는 식
System.out.println("점수의 합계: " + sum1); // 456
System.out.println("점수의 합계: " + sum2); // 456
double avg = (double) sum1 / scores.length;
// scores 배열의 길이만큼 합계의 값을 나누기
// sum과 scores.length 모두 정수 타입이기 때문에 소수점 값을 나타내야할 경우
// double로 형변환 해야함
System.out.println("평균: " + avg); // 91.2
}
}
-> 값의 목록은 없지만 향후 값들을 저장할 목적으로 배열을 미리 생성하기!
-> 배열 변수는 new 구문으로 생성과 동시에 값이 들어감!
-> 기본형 타입의 배열은 초기값이 0이 들어감 (실수는 0.0)
-> String 문자열타입의 변수는 초기값이 null이 들어감
-> 형태
타입[] 변수 = new 타입[길이];
타입[] 변수 = new 타입[길이] {값0,값1,값2,...}; 의 형태도 가능
-> 위와 같은 방식을 배열의 명시적 표현이라고 함!
-> 배열변수.length;의 형태를 띄며, 길이를 확인하는 것만 가능!
package ch05.sec06;
public class NewArrayExam {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] arr1 = new int[3];
// int 배열 선언 및 초기화 : 배열 길이 = 3
// new 타입[] 을 쓸때 []안에 무조건 배열 길이 수를 선언해주거나 배열 안에 값을 넣어야함
// 배열은 선언과 동시에 초기값이 설정이 됨
// int 타입 배열은 초기값이 0
for(int i=0;i<arr1.length;i++) {
//arr1 배열의 길이 수만큼 반복문 실행
System.out.println("arr1[" + i + "]=" + arr1[i]); // arr1[0~2]까지 모두 0으로 출력됨
}
System.out.println();
arr1[0] = 1; // arr1의 첫번째 배열에 1을 대입
arr1[1] = 2; // arr1의 두번째 배열에 1을 대입
arr1[2] = 3; // arr1의 세번째 배열에 1을 대입
for(int i=0;i<arr1.length;i++) {
System.out.println("arr1[" + i + "]=" + arr1[i]);
//arr1[0~2]의 값이 각각 1, 2, 3이 출력
}
System.out.println();
double[] arr2 = new double[3];
// double 배열 선언 및 초기화 : 배열 길이 = 3
//double 타입 배열의 초기값은 0.0
for(int i=0; i<arr2.length; i++) {
// arr2 배열의 길이 수만큼 반복문 실행
System.out.println("arr2[" + i + "]=" + arr2[i]);
// arr2[0~2]까지 모두 0.0으로 출력됨
}
System.out.println();
arr2[0] = 0.1; // arr2의 첫번째 배열에 0.1을 대입
arr2[1] = 0.2; // arr2의 두번째 배열에 0.2을 대입
arr2[2] = 0.3; // arr2의 세번째 배열에 0.3을 대입
for(int i=0;i<arr2.length;i++) {
System.out.println("arr2[" + i + "]=" + arr2[i]);
//arr2[0~2]의 값이 각각 0.1, 0.2, 0.3으로 출력됨
}
System.out.println();
String[] arr3 = new String[3];
// String 배열 선언 및 초기화 : 배열 길이 = 3
// String 타입은 참조형이기 때문에 heap의 번지 주소에서 값을 참조하는 형태이므로
// String 타입의 초기값은 null
for(int i=0;i<arr3.length;i++) {
// arr3 배열의 길이 수만큼 반복문 실행
System.out.println("arr3[" + i + "]=" + arr3[i]);
// arr3[0~2]까지 모두 null로 출력됨
}
System.out.println();
arr3[0] = "1일"; // arr3의 첫번째 배열에 "1일"을 대입
arr3[1] = "2일"; // arr3의 두번째 배열에 "2일"을 대입
arr3[2] = "3일"; // arr3의 세번째 배열에 "3일"을 대입
for(int i=0;i<arr3.length;i++) {
System.out.println("arr3[" + i + "]=" + arr3[i]);
// arr3[0~2]의 값이 각각 1일, 2일, 3일로 출력됨
}
}
}
-> 2차원 이상의 배열을 뜻함 : 일렬로 되어있는 배열이 층을 이루는 것
-> 배열 생성 방법
-> 명시적 생성 : 타입[][] 변수 = new int[(2차)][(1차)];
-> 배열의 길이를 미리 선언
-> 암시적 생성 : 타입[][] 변수 = {{값01, 값02,..}, {값11, 갑12,...};
-> 배열 생성 및 초기화!
-> 차원이 높아질수록 []의 갯수가 더 많아짐!
-> new 타입[][] 에서 차원안의 배열의 갯수를 지정하지 않을 경우 배열의 수가 값을 넣는 갯수에 따라 유동적으로 생성!
-> ex)
int[] scores = new int[2][3]에서
앞의 [2]는 배열 안의 중괄호의 갯수 (2차원 배열 갯수)
뒤의 [3]은 배열 안의 각 중괄호 안에 있는 값의 갯수 (1차원 배열 갯수)
package ch05.sec07;
public class MultipleArrayExam {
public static void main(String[] args) {
int[][] mathScores = new int[2][3];
// new 함수를 이용하여 다차원 배열을 생성함
// 자리수가 맞게 만들어짐
for(int i=0;i<mathScores.length;i++) {
for(int k=0;k<mathScores[i].length;k++) {
System.out.println("mathScores[" + i + "]" + "[" + k + "]=" + mathScores[i][k]);
}
}
// 초기값이 0이기 때문에 0이 출력됨
System.out.println();
mathScores[0][0] = 80;
mathScores[0][1] = 83;
mathScores[0][2] = 85;
mathScores[1][0] = 86;
mathScores[1][1] = 90;
mathScores[1][2] = 92;
int totalStudent = 0;
int totalMathSum = 0;
for(int[] mathScore : mathScores) {
totalStudent += mathScore.length;
for(int mathScore2 : mathScore) {
totalMathSum += mathScore2;
}
}
double totalMathAvg = (double)totalMathSum / totalStudent;
System.out.println("전체 학생의 수학 평균 점수= " + totalMathAvg);
System.out.println();
int[][] englishScores = new int[2][];
// 다차원 배열을
englishScores[0] = new int[2];
englishScores[1] = new int[3];
for(int i=0;i<englishScores.length;i++) {
for(int k=0;k<englishScores[i].length;k++) {
System.out.println("englishScores[" + i + "]" + "[" + k + "]=" + englishScores[i][k]);
}
}
englishScores[0][0] = 90;
englishScores[0][1] = 91;
englishScores[1][0] = 92;
englishScores[1][1] = 93;
englishScores[1][2] = 94;
totalStudent = 0;
int totalEnglishSum = 0;
for(int[] englishScore : englishScores) {
totalStudent += englishScore.length;
for(int englishScore2 : englishScore) {
totalEnglishSum += englishScore2;
}
}
double totalEnglishAvg = (double)totalEnglishSum / totalStudent;
System.out.println("전체 학생의 영어 평균 점수= " + totalEnglishAvg);
}
}
-> 기본형 배열 : 각 stack에 값을 직접 저장함
-> 참조형 배열 : heap에 값을 저장하고 heap에 저장된 주소를 참조함
-> 참조형 배열의 경우 비교 연산자 (==, !=)를 사용했을 때 값의 비교가 아닌 참조하는 주소를 비교함!
-> 문자열 비교를 위해서는 .equals 사용!
package ch05.sec08;
public class ArrayReference {
public static void main(String[] args) {
// TODO Auto-generated method stub
//암시적 배열 선언
String[] strArray = new String[3];
strArray[0] = "Java";
strArray[1] = "Java";
// strArray[0]과 같은 heap 번지 주소 사용
strArray[2] = new String("Java");
// 새로운 heap 번지 주소 사용
System.out.println(strArray[0] == strArray[1]);
// 같은 heap 번지 주소를 사용하기 때문에 true
System.out.println(strArray[0] == strArray[2]);
// 다른 heap 번지 주소를 사용하기 때문에 false
System.out.println(strArray[0].equals(strArray[2]));
// 문자열이 같으므로 true
// 참조 변수 비교 연산 : 문자열 등 값의 차이를 보는 것이 아닌 참조하는 heap 번지 주소의 차이를 봄
// *********** 명시적 배열 선언 (과제) *************//
String[] strArray1 = {"Java", "Java", new String("Java")};
System.out.println(strArray1[0] == strArray1[1]);
// 같은 heap 번지 주소를 사용하기 때문에 true
System.out.println(strArray1[0] == strArray1[2]);
// 다른 heap 번지 주소를 사용하기 때문에 false
System.out.println(strArray1[0].equals(strArray1[2]));
// 문자열이 같으므로 true
}
}
-> 배열은 한 번 생성하면 길이 변경이 불가함
-> for문을 통해 배열을 복사할 수 있음!
package ch05.sec09;
public class ArraycopyExam {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] oldIntArray = {1, 2, 3}; // 배열의 길이가 3
int[] newIntArray = new int[5];
// 길이가 5인 배열을 새로 선언 (초기값이 들어있음)
for(int i=0;i<oldIntArray.length;i++) {
//oldIntArray의 길이만큼 실행
newIntArray[i] = oldIntArray[i];
//new에 old 배열의 자리수의 값 그대로 복사
}
for(int i=0;i<newIntArray.length;i++) {
System.out.print(newIntArray[i] + " ");
}
// new 배열에 있는 값들을 나열 : 나머지 배열에는 초기값 0
System.out.println();
int[] oldIntArray1 = {1, 2, 3}; // 배열의 길이가 3
int[] newIntArray1 = new int[5];
// 길이가 5인 배열을 새로 선언 (초기값이 들어있음)
// 복사할 값의 자리수나 복사받을 값의 자리수를 다르게 해보기
// old의 1번째 값부터 new의 3번째 자리에 붙여넣기
for(int i=0;i<oldIntArray1.length;i++) { //oldIntArray의 길이만큼 실행
newIntArray1[i+2] = oldIntArray1[i];
}
// 복사하는 배열의 자리수가 넘어가면 indexOutException 발생
for(int i=0;i<newIntArray1.length;i++) {
System.out.print(newIntArray1[i] + " ");
}
}
}
-> 시스템에서 제공하는 배열 복사 방법
-> 성능이 우수해서 for문을 사용하는 것보다 고속으로 사용 가능!
-> 형태
System.arraycopy(a, b, c, d, e);
-> a : 원본배열의 변수
-> b : 원본배열에서 복사를 시작할 위치 (정수)
-> c : 복사할 배열의 변수
-> d : 복사할 배열에서 복사를 받기 시작할 위치 (정수)
-> e : 복사할 값의 갯수 (배열의 크기를 벗어나면 오류남)
package ch05.sec09;
public class systemArraycopyExam{
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] oldStrArray = {"집", "학원", "음식점"};
String[] newStrArray = new String[5];
System.arraycopy(oldStrArray, 0, newStrArray, 1, oldStrArray.length);
//System.arraycopy : 배열을 복사하는 곳
//시스템에서 제공하는 배열 복사 방법 : 고속!
//(원본배열, 원본배열의 시작위치, 복사할배열, 복사할배열의 시작위치, 복사할 값의 갯수)
for(int i=0;i<newStrArray.length;i++) {
System.out.println(newStrArray[i]);
} // newStrArray 출력
}
}
-> 2가지 버전이 있으며 for문을 더 간단하게 사용하는 방식!
-> 주로 배열을 이용할 때 많이 사용됨
-> 구조
for(타입 임의의변수 : 배열변수){
실행문
}
-> 동작원리
1. 사용하고자 하는 배열 변수 값을 임의의 변수에 집어 넣음
-> 임의의변수는 배열변수의 타입과 동일해야함!
2. 해당 배열의 값의 갯수만큼 실행됨
-> 구조
for(var 임의의변수 : 배열변수){
실행문
}
-> 동작원리는 for loop 1과 동일
-> 임의의 변수 타입에 var 타입을 사용했다는 것이 차이점
package ch05.sec10;
public class AdvancedFor {
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] scores = {95, 71, 84, 93, 87};
int sum = 0;
for(int score : scores) {
sum += score;
} // 향상된 for loop 1버전
System.out.println(sum);
System.out.println((double) sum / scores.length);
int[] scores1 = {95, 71, 84, 93, 87};
int sum1 = 0;
for(var score1 : scores1) {
sum1 += score1;
} // 향상된 for loop 2버전
System.out.println(sum);
System.out.println((double) sum / scores.length);
}
}
-> 구조
for(타입[] 임의의변수1 : 배열변수){
실행문 (2차원 배열 갯수에 대한 연산이 실행)
for(타입 임의의변수2 : 임의의변수1){
실행문 (배열 안의 값에 대한 연산이 실행)
}
}
-> 동작 원리
1. 다차원 배열의 변수를 선언하여 값을 가져오기
2. 가져온 배열변수의 값을 임의의변수1에 넣음
-> 이 때 다차원 배열의 갯수에 관한 연산을 진행하여 한 단계 아래 차원의 값으로 변형하는 과정이기에 타입 앞에 []를 해당 차원의 한 단계 차원의 갯수만큼 넣기!
3. 임의의변수1의 타입에 맞게 임의의변수2를 선언하여 배열 값을 받아 1차원 배열의 형태로 변형된 임의의변수1을 임의의변수2에 넣어 값의 형태로 변환!
-> 구조
for(var 임의의변수1 : 배열변수){
실행문 (2차원 배열 갯수에 대한 연산이 실행)
for(var 임의의변수2 : 임의의변수1){
실행문 (배열 안의 값에 대한 연산이 실행)
}
}
-> 동작원리
-> for loop 1과 동일
-> 해당 배열변수의 타입이 아닌 var를 사용하는 것이 특징
-> var의 경우 자동적으로 타입을 인식하기 때문에 다차원 배열이라도 []를 넣지 않아야 함!
//일반 for문
for(int i=0;i<scores.length;i++) {
// scores의 배열의 개수만큼 실행
int classSum = 0;
// 반별로 합계를 구할것이기 때문에 한 반의 합계를 구하고 다시 초기화
for(int k=0;k<scores[i].length;k++) {
// scores의 각 배열 안의 있는 값들의 합계를 구하기
classSum += scores[i][k];
// 1반 : 266, 2반 164
}
double classAvg = (double) classSum /scores[i].length;
// 반 점수 합계 / 각 반의 학생수
System.out.println((i+1) + "번째 반의 평균 점수: " + classAvg);
}
System.out.println();
//향상된 for문 ver 1
int a = 0;
// for 실행 횟수마다 몇 반인지 나타내기 위해 사용! 초기화 해야함
for(int[] scorefor1_1 : scores) {
// scores안의 배열들을 scorefor1_1에 대입
int classSum = 0;
// 반별로 합계를 구할것이기 때문에 한 반의 합계를 구하고 다시 초기화
a++;
for(int scorefor1_2 : scorefor1_1) {
// scorefor1_1에서 받은 배열들의 값을 scorefor1_2에 대입
classSum += scorefor1_2;
}
double classAvg1_1 = (double) classSum / scorefor1_1.length; // scores[i]의 길이 수!
System.out.println(a + "번째 반의 평균 점수: " + classAvg1_1);
// a: 반을 정수 형태로 나타낸 것!
}
System.out.println();
// 향상된 for문 ver 2
int b = 0;
for(var scorefor1_1 : scores) {
// var : 타입을 자동적으로 파악하기 때문에 다차원 배열에서도 []를 사용하지 않음
int classSum = 0;
b++;
for(var scorefor1_2 : scorefor1_1) {
classSum += scorefor1_2;
}
double classAvg1_1 = (double) classSum / scorefor1_1.length; // scores[i]의 길이 수!
System.out.println(b + "번째 반의 평균 점수: " + classAvg1_1);
}
System.out.println();