배열

이동주·2025년 3월 2일

JAVA

목록 보기
12/30

배열

반복적인 코드를 간단하게 표현하기 위해 만든 것!

-> 연속된 공간에 값을 나열시키고, 각 값에 인덱스를 부여해 놓는 자료 구조! (색인 배열)
-> 인덱스는 대괄호 []와 함께 사용하여 각 항목의 값을 읽거나 사용하는데 사용!
-> 힙 영역에 생성되고 배열 변수는 힙 영역의 배열 주소를 저장
-> 참조할 변수가 없을 경우 변수를 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 연산자로 배열 생성하기

-> 값의 목록은 없지만 향후 값들을 저장할 목적으로 배열을 미리 생성하기!
-> 배열 변수는 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] + " ");
		}
		
	}

}

System.arraycopy()

-> 시스템에서 제공하는 배열 복사 방법
-> 성능이 우수해서 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 출력
	}

}

향상된 for문

-> 2가지 버전이 있으며 for문을 더 간단하게 사용하는 방식!
-> 주로 배열을 이용할 때 많이 사용됨

향상된 for loop 1 버전

-> 구조
for(타입 임의의변수 : 배열변수){
실행문
}

-> 동작원리
1. 사용하고자 하는 배열 변수 값을 임의의 변수에 집어 넣음
-> 임의의변수는 배열변수의 타입과 동일해야함!
2. 해당 배열의 값의 갯수만큼 실행됨

향상된 for loop 2 버전

-> 구조
for(var 임의의변수 : 배열변수){
실행문
}

-> 동작원리는 for loop 1과 동일
-> 임의의 변수 타입에 var 타입을 사용했다는 것이 차이점

  • 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 loop

for loop 1

-> 구조
for(타입[] 임의의변수1 : 배열변수){
실행문 (2차원 배열 갯수에 대한 연산이 실행)
for(타입 임의의변수2 : 임의의변수1){
실행문 (배열 안의 값에 대한 연산이 실행)
}
}

-> 동작 원리
1. 다차원 배열의 변수를 선언하여 값을 가져오기
2. 가져온 배열변수의 값을 임의의변수1에 넣음
-> 이 때 다차원 배열의 갯수에 관한 연산을 진행하여 한 단계 아래 차원의 값으로 변형하는 과정이기에 타입 앞에 []를 해당 차원의 한 단계 차원의 갯수만큼 넣기!
3. 임의의변수1의 타입에 맞게 임의의변수2를 선언하여 배열 값을 받아 1차원 배열의 형태로 변형된 임의의변수1을 임의의변수2에 넣어 값의 형태로 변환!

for loop 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();
profile
끄작끄작

0개의 댓글