[Chapter 5] 배열 (Array)

slchoi·2022년 1월 7일
0

자바의 정석

목록 보기
10/19
post-thumbnail

'자바의 정석 3rd Edition'을 공부하며 정리한 내용입니다.

1. 배열(array)


1.1 배열(array)이란?

  • 배열(array): 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것
  • 변수의 선언과 달리 다워야할 데이터의 수가 많을 경우 배열의 길이만 바꾸면 됨
int [] score = new int[5];	// 5개의 int 값을 저장할 수 있는 배열을 생성
  • 변수 score은 배열을 다루는데 필요한 참조변수일 뿐 값을 저장하기 위한 공간은 아님
  • 변수와 달리 배열은 각 저장공간이 연속적으로 배치되어 있음

1.2 배열의 선언과 생성

1. 배열 선언

타입[] 변수이름;
or
타입 변수이름[];
  • 원하는 타입의 변수를 선언하고 변수 또는 타입에 배열임을 의미하는 대괄호[]를 붙이면 됨
    • []는 타입 뒤에 붙여도 되고 변수이름 뒤에 붙여도 됨

2. 배열 생성

타입[] 변수이름;			// 배열 선언 (참조변수 선언)
변수이름 = new 타입[길이];	// 배열 생성 (실제 저장공간을 생성)

or

타입[] 변수이름 = new 타입[길이];	// 배열의 선언과 생성을 동시에

3. 배열의 선언과 생성과정

  • 배열 참조변수 선언. 아직 데이터를 저장할 수 있는 공간은 마련되지 않음
  • 연산자 new에 의해 메모리의 빈 공간에 5개의 int형 데이터를 저장할 수 있는 공간이 마련됨
    • int의 경우 각 배열요소는 자동적으로 기본값(default)인 0으로 초기화
  • 대입 연산자 '='에 의해 배열의 주소가 배열 참조변수에 저장됨
  • 참조변수를 통해 생성된 배열에 값을 저장하거나 읽어올 수 있음

1.3 배열의 길이와 인덱스

  • 배열의 요소(element): 생서된 배열의 각 저장공간
    • '배열이름[인덱스]' 형식으로 배열의 요소에 접근

1. 배열의 인덱스

  • 인덱스(index): 배열의 요소마다 붙여진 일련번호
    • 각 요소를 구별하는데 사용
    • 범위: 0 ~ (배열길이 - 1)
  • index로 상수 대신 변수나 수식도 사용 가능
    • for문의 제어변수 i는 배열의 index로 사용하기 좋아서 배열을 다룰 때 for문은 거의 필수적
    • index에 수식이 포함된 경우, 수식이 먼저 계산됨
  • index의 범위를 벗어난 값을 index로 사용하지 않아야 함
    • 컴파일러는 이 실수를 걸러주지 못함. 배열의 index로 변수를 많이 사용하는데, 변수의 값은 실행 시에 대입되므로 컴파일러는 이 값의 범위를 확인할 수 없기 때문
    • 유효하지 않은 값을 index로 사용하면 컴파일을 마쳤더라도 실행 시에 에러 발생

2. 배열의 길이

  • 배열의 길이: 배열의 요소의 개수, 즉 값을 저장할 수 있는 공간의 개수
  • 양의 정수이어야 하며 최대값은 int의 최대값(약 20억)
  • 길이가 0인 배열도 생성 가능
  • 배열이름.length: 배열의 길이에 대한 정보를 얻을 수 있음
    • 배열은 한번 생성하면 길이를 변경할 수 없기 때문에, 이미 생성된 배열의 길이는 변하지 않음
    • 배열이름.length는 상수 => 값을 읽을 수만 있을 뿐 변경할 수 없음
    • for문의 조건식에 배열의 길이를 직접 적어주는 것보다 '배열이름.length'를 사용하는 것이 좋음
      • '배열이름.length'는 배열의 길이가 변경되면 자동적으로 변경된 배열의 길이를 값으로 갖기 때문에 for문의 조건식을 일일이 변경해주지 않아도 됨
  • 배열의 길이 변경하기
    • 더 큰 길이의 새로운 배열을 생성한 후 기존 배열의 내용을 새로운 배열에 복사
    • 처음부터 길이를 넉넉하게 잡아 새로 배열을 생성해야하는 상황이 가능한 적게 발생하도록 해야 함
    • 너무 크게 잡을 경우 메모리 낭비가 발행하므로, 기존의 2배 정도의 길이로 생성하는 것이 좋음
    • '1.5 배열의 복사' 부분 참고

1.4 배열의 초기화

  • 배열은 생성과 동시에 자동적으로 자신의 타입에 해당하는 기본값으로 초기화되므로 배열을 사용하기 전에 따로 초기화를 해주지 않아도 됨
  • 원하는 값을 저장하려면 각 요소마다 값을 지정해줘야 함
    • 배열의 길이가 큰 경우 for문을 사용하는 것이 좋음
    • for문으로 배열을 초기화하려면, 저장하려는 값에 일정한 규칙이 있어야만 가능하기 때문에 자바에서는 배열을 간단히 초기화 할 수 있는 방법을 제공
    int[] score = new int[] {50, 60, 70, 80, 90};
    • {} 안의 값의 개수에 의해 배열의 길이가 자동적으로 결정되므로 배열의 길이는 안 적어도 됨
    • new 타입[] 부분 생략 가능. 단, 배열의 선언과 생성을 따로 하는 경우 생략 불가
    • {} 괄호 안에 아무 것도 넣지 않을 경우 길이가 0인 배열이 생성됨
      • 참조변수의 기본 값은 null이지만, 배열을 가리키는 참조변수는 null대신 길이가 0인 배열로 초기화하기도 함

배열의 출력

  • 배열에 저장된 값을 확인할 때는 for문 혹은 Arrays.toString(배열이름) 메서드 사용
    • Arrays.toString(배열이름): 배열의 모든 요소를 '[첫번째 요소, 두번째 요소, ...]'와 같은 형식의 문자열로 만들어 반환
    • 메서드 사용을 위해서는 import java.util.*를 추가

1.5 배열의 복사

1. for문 이용한 배열의 복사

int[] arr = new int[5];
      ...
int[] tmp = nenw int[arr.length*2];	// 기존 배열보다 길이가 2배인 배열 생성

for (int i=0; i<arr.length; i++)
	tmp[i] = arr[i];	// arr[i]의 값을 tmp[i]에 저장

arr = tmp;	// 참조변수 arr이 새로운 변수를 가리키게 함

사진 출처: 자바의 정석 3rd Edition p.193

  • 참조변수 arr과 tmp는 같은 배열을 가리키게 됨. 이름만 다를 뿐 동일한 배열
    • 전에 arr이 가리키던 배열은 더 이상 사용할 수 없게 됨
    • 배열은 참조변수를 통해서만 접근 가능. 자신을 가리키는 참조변수가 없는 배열은 사용 불가. 쓸모없게 된 배열은 JVM의 가비지 컬렉터에 의해 자동적으로 메모리에서 제거됨
  • 처음부터 길이를 넉넉하게 잡아 새로 배열을 생성해야하는 상황이 가능한 적게 발생하도록 해야 함
  • 너무 크게 잡을 경우 메모리 낭비가 발행하므로, 기존의 2배 정도의 길이로 생성하는 것이 좋음

2. System.arraycopy()를 이용한 배열의 복사

System.arraycopy(num, 0, newNum, 0, num.length);
=> num[0]에서 newNum[0]으로 num.length개의 데이터를 복사
  • System 클래스의 arraycopy()를 상요하면 간단하고 빠르게 배열 복사 가능
  • for문은 배열의 요소 하나하나에 접근해서 복사하지만, arraycopy()는 지정된 범위의 값들을 한 번에 통째로 복사
    • 각 요소들이 연속적으로 저장되어 있는 배열의 특성 때문에 가능한 방법
  • 복사하려는 배열의 위치가 적절하지 못하여 복사하려는 내용보다 여유 공간이 적으면 에러가 발생

1.6 배열의 활용

임의의 값으로 배열 채우기

for (i=0; i<arr.length; i++) {
	arr[i] = (int) (Math.random()*5);  // 0~4 범위의 임의의 값 저장
}

2. String 배열


2.1 String 배열의 선언과 생성

// 3개의 문자열을 담을 수 있는 배열 생성
String[] name = new String[3];
  • String 타입의 참조변수를 저장하기 위한 공간이 마련되고 참조형 변수의 기본값은 null이므로 각 요소의 값은 null로 초기화
    • null: 어떠한 객체도 가리키고 있지 않다는 의미
  • 변수의 타입에 따른 기본값
자료형기본값
booleanfalse
char'\u0000'
byte, short, int0
long0L
float0.0f
double0.0d 또는 0.0
참조형 변수null

2.2 String 배열의 초기화

  • 배열과 동일
  • 참조형 배열(객체 배열)의 경우 배열에 저장되는 것은 객체의 주소

2.3 char 배열과 String 클래스

  • String 클래스는 char 배열에 기능(메서드)를 추가한 것
    • 객체지향개념이 나오기 이전의 언어는 데이터와 기능을 따로 다루었지만, 객체지향언어에서는 데이터와 그에 관련된 기능을 하나의 클래스에 묶어서 다룰 수 있게 함. 즉, 서로 관련된 것들끼리 데이터와 기능을 구분하지 않고 함께 묶는 것
    • '기능'은 함수를 의미. 메서드는 객체지향 언어에서 함수 대신 사용하는 용어
  • String 객체는 읽을 수만 있을 뿐 애요을 변경할 수 없음
    • 변경 가능한 문자열을 다루려면, StringBuffer 클래스를 사용하면 됨 => 9장에서 설명

1. String 클래스의 주요 메서드

메서드설명
char charAt(int index)문자열에서 해당 위치(index)에 있는 문자를 반환
int length()문자열의 길이를 반환
String substring(int from, int to)문자열에서 해당 범위에 있는 문자열을 반환 (to는 포함하지 않음)
boolean equals(Object obj)문자열의 내용이 obj와 같은지 확인 (대소문자 구분 O)
boolean equalsIgnoreCase(Object obj)문자열의 내용이 obj와 같은지 확인 (대소문자 구분 X)
char[] toCharArray()문자열을 문자배열(char[])로 변환해서 반환

2. char 배열과 String 클래스의 변환

  • char 배열을 String 클래스로 변환하거나 반대로 변환해야하는 경우
char[] chArr = {'A', 'B', 'C'};
String str = new String(chArr);	// char 배열 -> String
char[] tmp = str.toCharArray(); // String -> char 배열

2.4 커맨드 라인을 통해 입력받기

  • 프로그램을 실행할 때 클래스 이름 뒤에 공백문자로 구분하여 여러 개의 문자열을 프로그램에 전달 할 수 있음
  • 커맨드라인에 입력된 매개변수는 공백문자로 구분하기 때문에 입력될 값에 공백이 있는 경우 ""로 감싸주어야 함
  • 커맨드라인에서 숫자를 입력해도 숫자가 아닌 문자열로 처리됨
  • 커맨드라인에 매개변수를 입력하지 않으면 크기가 0인 배열이 생성됨

3. 다차원 배열


3.1 2차원 배열의 선언과 인덱스

1. 선언 방법

타입[][] 변수이름;
타입 변수이름[][];
타입[] 변수이름[];
  • 2차원 배열은 주로 테이블 형태의 데이터를 담는데 사용

2. 2차원 배열의 Index

  • 2차원 배열은 행과 열로 구성되어 있기 때문에 index도 행과 열에 각각 하나씩 존재
    • 행 index의 범위: 0 ~ 행의길이-1, 열 index의 범위: 0 ~ 열의길이-1
  • 2차원 배열의 각 요소에 접근하는 방법: 배열이름[행index][열index]

3.2 2차원 배열의 초기화

  • {}를 사용해 생성과 초기화를 동시에 할 수 있음. {}를 한번 더 써서 행별로 구분
int[][] arr = {{1, 2, 3}, {4, 5, 6}};	// new int[][] 생략

int[][] arr = {
			{1, 2, 3}, 
			{4, 5, 6}
               };
  • 2차원 배열은 '배열의 배열'로 구성됨. 여러 개의 1차원 배열을 묶어서 또 하나의 배열로 만든 것

3.3 가변 배열

  • 다차원 배열을 생성할 때 전체 배열 차수 중 마지막 차수의 길이를 지정하지 않고, 추후에 각기 다른 길이의 배열을 생성함으로써 고정된 형태가 아닌 유동적인 가변 배열을 구성할 수 있음
  • 각 행마다 다른 길이의 배열을 생성하는 것이 가능
  • {}를 이용해 생성과 초기화를 동시에 하는 것이 가능

Chapter 5 끝!!!

profile
예비 백엔드 개발자

0개의 댓글