남궁성 저자의 Java의 정석 3판 스터디
기초로 돌아가는 마음으로 Java의 정석을 읽으며 스터디를 시작했다 🙂
챕터마다 중요하거나 몰랐던 부분들을 정리해보고자 한다.
배열이란
같은 타입의 여러 변수를 하나의 묶음으로 다루는 것
배열의 선언과 생성
자바에서 배열을 생성할 때는 아래와 같이 한다.
int[] arr = new int[5]; // 가능
int[] arr = new int[] {50, 60, 70} // 가능
int[] arr;
arr = {50, 60, 70} // 이건 불가능
그런데, 길이가 0인 배열도 생성이 가능하다 !
int[] arr = new int[0];
길이가 0인 배열을 생성하는 것은 어떤 의미가 있을까?
Java에서 main method 실행할 때를 생각해보자.
class Example {
public static void main(String[] args) {
// main
System.out.println("매개변수의 개수 : " + args.length);
}
}
// CLI
$juwon > java Example
위 코드를 보면 커맨드라인에 매개변수를 입력하지 않았다.
입력된 매개변수가 없다고 배열을 생성하지 않으면 args 의 값은 null 이 될 것이고,
args 를 사용하는 코드에서 에러가 발생할 것이다.
바로 여기서 JVM이, 입력된 매개변수가 없을 때 null 대신 크기가 0인 배열을 생성해서
args 에 전달하도록 구현되어 있다.
실제로 위 코드를 실행해보면 0이 출력된다 !
배열은 index를 이용해서 접근할 수 있다.
index의 범위는 0부터 배열길이 -1
까지이다.
index의 범위를 벗어나면 에러(ArrayIndexOutOfBoundsException
)가 발생한다.
Java에서는 JVM이 모든 배열의 길이를 별도로 관리한다.
배열의 길이 정보는 배열이름.length
를 통해서 얻을 수 있다.
int[] arr = new int[5]; // 길이가 5인 int 배열
int tmp = arr.length; // arr.length 값은 5
배열은 한 번 생성하면 길이를 변경할 수 없다.
따라서 배열의 길이인 배열이름.length
는 상수이다. 읽을 수만 있고 변경 불가 !
배열의 길이를 늘리고 싶으면 더 큰 공간을 할당받아서 복사하기 !
배열의 복사
배열의 공간이 부족할 때, for 문을 이용해서 복사할 수 있다.
쉬운 코드지만 뒤의 System.arraycopy()
와의 비교를 위해 적어본다.
// 기존 배열
int[] arr = new int[5];
// 기존 배열보다 길이가 2배인 새 배열 생성
int[] tmp = new int[arr.length * 2];
for (int i = 0; i < arr.length; i++) {
tmp[i] = arr[i]; // arr[i]의 값을 tmp[i]에 저장
}
arr = tmp; // arr 이 새로운 배열을 가리키게 함
for문 대신에 System.arraycopy()
를 사용하면 더 효율적으로 배열을 복사할 수 있다.
for문은 배열의 요소 하나하나를 복사하지만, arraycopy() 는 지정된 범위의 값들을 한 번에 복사한다.
for (int i = 0; i < arr.length; i++) { newArr[i] = arr[i] }
// 위 코드를 arraycopy() 로 바꾸면 아래와 같다
System.arraycopy(arr, 0, newArr, 0, arr.length);
arraycopy() 의 파라미터는 다음 순서로 기억하자.
(원본배열
, 원본배열 index
, 타겟배열
, 타겟배열 index
, 복사할 데이터 개수
)
배열의 활용
배열을 활용한 간단한 예제들을 작성해보자.
총합과 평균 구하기
int sum = 0;
float avg = 0f;
int[] score = {100, 88, 100, 100, 90};
for (int i = 0; i < score.length; i++) {
sum += score[i];
}
avg = sum / (float)score.length; // 계산결과를 float로 얻기 위해 형변환
shuffle
int[] numArr = new int[10];
for (int i = 0; i < numArr.legnth; i++) {
numArr[i] = i;
}
for (int i = 0; i < numArr.length; i++) {
int n = (int)(Math.random() * 10);
int tmp = numArr[i];
numArr[i] = numArr[n];
numArr[n] = tmp;
}
로또번호 생성
int[] ball = new int[45];
for (int i = 0; i < ball.length; i++) {
ball[i] = i + 1;
}
int tmp = 0;
int j = 0;
for (int i = 0; i < 6; i++) {
j = (int)(Math.random() * 10);
tmp = ball[i];
ball[i] = ball[j];
ball[j] = tmp;
}
// 0~5 index 요소 출력
bubble sort
int[] arr = new int[10];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int)(Math.random() * 10);
}
for (int i = 0; i < arr.length-1; i++) {
boolean changed = false;
for (int j = 0; j < arr.length-1-i; j++) {
if (arr[j] > arr[j+1]) {
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
changed = true;
}
}
if (!changed) break;
}
다차원 배열
2차원 배열을 이해하면 3차원, 4차원 배열도 이해할 수 있다..~
2차원 배열을 선언할 때는
int[][] arr = new int[2][3];
// or
int[][] arr = {
{1,2,3},
{4,5,6}
};
이렇게 하면 된다.
2차원 배열은 배열의 배열
로 구성되어 있다.
중요한 점은 2차원 배열 arr 가 어떤 형태로 만들어지는지 그릴 수 있어야 한다는 것 !
arr.length 는 얼마이고, arr[0].length 는 얼마일까 ??
정답은 ~_~
arr.length : 2
arr[0].length : 3
이거 틀렸으면 배열 다시 공부하자..
++ 추가 ++
같이 스터디를 진행하는 친구가 작성한 코드인데
다차원 배열에서 stream 을 적용한 것이 재밌어서 가져왔다.
다차원 배열 arr 를 일렬로 나열한 후 람다 함수를 이용해 하나씩 프린트 찍기 !
Arrays.stream(arr).flatMapToInt(Arrays::stream)
.filter(o-> o < 4)
.forEach(System.out::println);