TIL

TIL_20220901

번잔중 2022. 9. 1. 18:24

오늘 할 일

🦎 코드스테이츠 10일차

  • 배열: 1차원 2차원 가변 배열, 배열 탐색 등

오늘 배운 것

📦 배열

동일한 타입의 값들을 하나의 묶음으로 묶은 자료 구조를 의미한다.

즉, 각 값들이 같은 의미를 지니면서 서로 연관성이 있을 때, 이들을 하나의 덩어리로 묶을 수 있으며, 이렇게 묶여진 값들의 집합을 배열이라고 한다.

 

메모리의 구조(RAM)

  • 메모리는 여러 개의 메모리셀로 이루어져 있다.
  • 각 메모리셀은 값을 저장할 수 있는 1byte 크기의 메모리 공간을 가지고 있다.
  • 16진수로 이루어진 메모리 주소가 지정되어 있고, 메모리 주소는 오름차순이다.
  • 만약 int형이라면 메모리셀을 4개 사용하고, double형이면 8개를 사용한다.
  • 일반 변수는 변수의 주소가 데이터를 저장하고 있지만 배열 변수는 변수의 주소가 배열의 첫번째 값의 주소를 가리키고 있다.
  • 배열이 가진 각 값들을 배열의 요소(element)라고 한다.
  • 배열의 각 요소는 0에서부터 시작하는 번호를 부여받는데, 이처럼 배열의 각 요소가 부여받는 순번을 인덱스(index)라고 한다.
// 일반적인 선언
String userName1 = "엄복동";
String userName2 = "김두한";
...
String userName22 = "호나우두";

// 배열
String[] userName = { "엄복동", "김두한", ..., "호나우두" };

 

배열의 차원이란?

배열과 관련하여 언급되는 ‘차원’이라는 것은 배열이 중첩된 정도를 의미한다. 즉, 배열이 중첩되었다 함은, 배열의 요소가 또 다른 배열인 경우를 의미한다.
  • 1차원 배열 : 배열이 중첩이 없는 경우 = 배열의 요소가 배열이 아닌 경우
    • 예 : { 1, 2, 3, 4 } - 배열의 각 요소는 1, 2, 3, 4로 모두 정수형의 값이다.
  • 2차원 배열 : 배열이 한 번 중첩된 경우 = 배열의 요소가 배열인 경우
    • 예 : { { 1, 2, 3, 4 }, { 5, 6, 7, 8 } } - 배열의 각 요소로 배열이 들어가 있다.

1차원 배열

1차원 배열의 선언과 초기화

1차원 배열은 가장 일반적인 배열의 형태로, 배열의 요소가 배열이 아닌 배열을 의미한다. 1차원 배열을 선언할 때에는 다음과 같이 타입 뒤에 대괄호를 붙여서 선언하고 초기화할 수 있다.
String[] userName = { "엄복동", "김두한", ..., "호나우두" };

1. 참조 변수 userName이 선언된다.

2. 배열이 생성되고 중괄호({ }) 내의 값으로 배열 요소들의 값이 초기화된다.

3. 생성된 배열의 첫 번째 요소의 주소값이 참조 변수 userName에 할당된다.

 

배열이 참조 변수인 이유

기본 타입의 변수는 컴퓨터의 입장에서 정해진 크기만큼의 메모리를 할당하면 된다. char는 2btye, int는 4byte처럼 정해진 크기가 있기 때문이다. 

하지만 배열의 경우는 선언을 할 당시에 크기를 짐작할 수가 없다. 그래서 참조 변수로 선언해 만들어질 배열의 주소값을 담을 메모리 공간만 확보하고, 배열이 생성되면 배열의 시작 주소값을 참조 변수에 할당하는 것이다.

상기 이유로 배열을 그냥 출력하게 되면 배열의 주소값이 출력된다. 배열의 데이터를 출력하고 싶다면 Array.toString() 메서드를 통해 가능하다.

String[] userName = {"엄복동", "김두한", "호나우두"};

System.out.println(userName); // [I@294u10294 같은 형태의 주소값
System.out.println(Array.toString(userName)); // ["엄복동", "김두한", "호나우두"]

 

값 접근하기

배열 내 특정 요소에 할당되어져 있는 값에 접근하려면 배열 참조 변수의 이름과 배열의 인덱스를 활용하면 된다. 즉, 배열_참조_변수_이름[인덱스]로 배열의 요소에 접근할 수 있다.

배열이 생성되고 나면 배열 첫 번째 요소의 주소값이 참조 변수에 할당되고, 배열의 각 요소는 0부터 시작하는 인덱스를 가진다.

배열_참조_변수_이름[인덱스]라고 입력하면 참조 변수가 가진 배열 첫 번째 요소의 주소값에 '인덱스 * 요소의 크기'를 더하여 얻을 수 있는 수를 주소로 가진 요소의 값을 읽어온다.

 

배열의 길이

배열이 가진 요소의 개수를 배열의 길이 또는 크기라고 한다. 배열의 길이는 배열_참조_변수_이름.length로 얻을 수 있다.
  • 배열의 길이 - 1이 배열 마지막 요소의 인덱스이다.
String[] userName = new String[22];

System.out.println(userName.length); // 22

2차원 배열

2차원 배열이란?

2차원 배열은 배열의 각 요소가 또 다른 배열인 구조일 뿐, 1차원 배열과 크게 다른 점은 없다.

 

2차원 배열의 선언과 초기화

1차원 배열에 대괄호를 하나 더 써주면 된다.
int[][] weight;
weight = new int[31][3];

// 한 줄로 작성
int[][] weight = new int[31][3];

 

이 2차원 배열의 내부 배열은 int형의 기본값인 0을 3개씩 저장하고 있으며, 외부 배열은 내부 배열({ 0, 0, 0 }) 31개를 저장하고 있다.

즉, 내부 배열은 3개의 0을 요소로 가지지만, 외부 배열의 각 요소는 내부 배열의 주소값을 저장하고 있다.

{
	{ 0, 0, 0 },
	{ 0, 0, 0 },
	{ 0, 0, 0 },

	...

	{ 0, 0, 0 }
}

// 선언과 초기화를 하나의 문장으로 할 때에 한해 new int[][]를 생략할 수 있다. 
int[][] weight = { 
	{ 65, 67, 68 }, 
	{ 70, 72, 73 }, 
	{ 71, 72, 73 },
	
	...

	{ 75, 77, 78 }
}

가변 배열

배열이 2차원 이상일 때, 마지막 차수에 해당하는 배열의 길이를 고정하지 않아도 되며, 이러한 배열을 가변 배열이라고 한다.

선언 및 초기화

이 때 생성된 것은 내부 배열의 크기를 자유롭게 지정할 수 있는 외부 배열이다. 즉, 외부 배열만 생성된 상태이다.

내부 배열을 생성하려면 new int[]를 사용하여 외부 배열의 각 요소에 할당해주면 된다.

int[][] ages = new int[5][];
System.out.println("Arrays.toString(ages) = " + Arrays.toString(ages));

// 결과
// Arrays.toString(ages) = [null, null, null, null, null]

ages[0] = new int[5];
ages[1] = new int[6];
ages[2] = new int[7];
ages[3] = new int[8];  
ages[4] = new int[9];

System.out.println("Arrays.toString(ages[0]) = " + Arrays.toString(ages[0]));
System.out.println("Arrays.toString(ages[1]) = " + Arrays.toString(ages[1]));
System.out.println("Arrays.toString(ages[2]) = " + Arrays.toString(ages[2]));
System.out.println("Arrays.toString(ages[3]) = " + Arrays.toString(ages[3]));
System.out.println("Arrays.toString(ages[4]) = " + Arrays.toString(ages[4]));

// 결과
// Arrays.toString(ages[0]) = [0, 0, 0, 0, 0]
// Arrays.toString(ages[1]) = [0, 0, 0, 0, 0, 0]
// Arrays.toString(ages[2]) = [0, 0, 0, 0, 0, 0, 0]
// Arrays.toString(ages[3]) = [0, 0, 0, 0, 0, 0, 0, 0]
// Arrays.toString(ages[4]) = [0, 0, 0, 0, 0, 0, 0, 0, 0]

// 생성과 동시에 초기화
int[][] ages = {
	{ 30, 32, 39, 59, 23 },
	{ 31, 41, 52, 56, 72, 13 },
	{ 45, 32, 84, 23, 13, 42, 55 },
	{ 23, 41, 62, 64, 23, 51, 67, 98 },
	{ 13, 14, 17, 84, 52, 37, 68, 66, 33 }
};

배열 탐색

문자열을 반복문으로 순회하고 탐색했던 것과 비슷한 방법으로 배열을 순회할 수 있다.

 

반복문을 통한 배열 탐색

// 일반적인 for문으로 배열을 순회하여 총합을 구하는 코드
int[] scores = { 100, 90, 85, 95, 100 };
int sum = 0;

for (int i = 0; i < scores.length; i++) {
	sum += scores[i];
}
System.out.println(sum); // 470

// while문을 통한 배열 순회
int[] scores = { 100, 90, 85, 95, 100 };
int sum = 0;
int i = 0;

while (i < scores.length) {
	sum += scores[i++];
}
System.out.println(sum); // 470

// 향상된 for문(Enhanced for문)
// 향상된 for문은 배열의 값을 읽어오는 것만 가능하다. 순회하면서 수정할 수 없다.
int[] scores = { 100, 90, 85, 95, 100 };
int sum = 0;

for (int score: scores) {
	sum += score;
}
System.out.println(sum); // 470

느낀점

  • 배열에 대한 개념은 알고 있었지만 메모리 관련 내용은 정확히 알지 못했는데, 정리할 수 있는 시간이어서 좋았다.
  • 페어 프로그래밍을 3일간 같은 분과 하다보니 금새 친해지고 편해졌다. 좋은 분이라 그런 것 같다!
  • 자바 언어를 배운지가 4년이 넘어가고 이렇게 연습해 본적이 없었기 때문에 아직 익숙하지가 않다. 주말 동안 이것 저것 만들어보면서 연습해봐야겠다.
  • 못 풀었던 문제가 두 개 있었는데, 집요하게 매달려서 풀어봐야겠다.

내일 할 일

🌮 코드스테이츠 11일차

  • 객체지향프로그래밍 기초: 클래스와 객체
  • 1일 1커밋