값 하나에 변수 하나씩 만들다 보면 금방 감당이 안 됩니다. 자바에는 여러 값을 한 덩어리로 담는 도구가 두 갈래로 있습니다. 단순한 배열과 유연한 컬렉션입니다. 배열을 먼저 다룬 뒤 그 한계에서 컬렉션으로 넘어가겠습니다.
배열 — 번호표를 붙여 한 줄로 세우기
배열은 같은 자료형의 값을 정해진 개수만큼 한 줄로 늘어놓은 그릇이며, 만드는 방법은 두 가지입니다.
// 방법 1 — 크기만 정하고 나중에 채우기
int[] viewCounts = new int[5];
viewCounts[0] = 320;
// 방법 2 — 값을 나열해 한 번에 만들기
String[] noteTitles = {"자바 입문", "변수와 자료형", "연산자와 제어문"};
System.out.println(noteTitles[1]); // 변수와 자료형
System.out.println(noteTitles.length); // 3
번호(인덱스)는 0부터 시작하므로 값이 3개인 배열의 마지막 칸은 [2]입니다. 가장 많이 넘어지는 곳입니다.
System.out.println(noteTitles[3]); // ArrayIndexOutOfBoundsException
없는 칸을 건드리면 프로그램이 그 자리에서 멈춥니다. 반복 조건에 i <= 배열.length를 쓰면 한 칸을 더 넘어가 반드시 이 오류를 만나므로 i < 배열.length가 정답입니다. 길이도 배열은 length, 문자열은 length()로 괄호 유무가 다릅니다.
new int[5]로 만든 다섯 칸은 비어 있는 것이 아니라 0으로, 참조형 배열이라면 null로 채워집니다.
2차원 배열 — 표 모양의 데이터
배열의 각 칸에 다시 배열을 넣으면 표가 됩니다. 주차별 조회수처럼 행과 열이 있는 자료에 어울립니다.
int[][] weeklyView = {
{120, 340, 90},
{210, 80, 500}
};
System.out.println(weeklyView[1][2]); // 500
System.out.println(weeklyView.length); // 2 (행 개수)
System.out.println(weeklyView[0].length); // 3 (열 개수)
읽는 순서는 [행][열]이고, 전부 훑으려면 반복문을 두 겹으로 씁니다.
for (int row = 0; row < weeklyView.length; row++) {
int sum = 0;
for (int col = 0; col < weeklyView[row].length; col++) {
sum += weeklyView[row][col];
}
System.out.println((row + 1) + "주차 합계: " + sum);
}
안쪽 조건에 [0].length가 아니라 [row].length를 쓴 이유가 있습니다. 자바는 행마다 열 개수가 다른 배열도 허용하기 때문입니다.
향상된 for문 — 번호가 필요 없을 때
순서대로만 훑으면 되는 경우에는 향상된 for문이 훨씬 짧고 안전합니다.
for (String title : noteTitles) {
System.out.println("- " + title);
}
“값을 하나씩 꺼내 title에 담아라”로 읽으면 됩니다. 인덱스를 다루지 않으니 범위를 벗어날 걱정이 없습니다. 다만 몇 번째인지 알아야 한다면 일반 for문을 써야 합니다.
배열의 한계와 ArrayList
배열의 결정적인 약점은 크기가 만들 때 고정된다는 점입니다. 크기 3으로 만들었는데 네 번째 글이 올라오면 더 큰 배열을 새로 만들어 값을 전부 옮겨야 합니다. ArrayList는 이 문제를 해결한 도구로, 넣으면 알아서 늘어나고 빼면 뒤의 값이 당겨집니다.
import java.util.ArrayList;
ArrayList<String> titles = new ArrayList<>();
titles.add("자바 입문");
titles.add("변수와 자료형");
titles.add("연산자와 제어문");
titles.remove(0);
System.out.println(titles.size()); // 2
System.out.println(titles.get(0)); // 변수와 자료형
<String>은 문자열만 담겠다는 선언입니다. 크기는 size(), 값 꺼내기는 get()으로 배열과 다릅니다. 직접 만든 클래스의 객체도 ArrayList<CardNote>처럼 담을 수 있습니다.
HashMap과, 그래서 무엇을 골라야 하는가
순서가 아니라 이름표로 값을 찾을 때는 열쇠(key)와 값(value)을 짝지어 저장하는 HashMap을 씁니다.
import java.util.HashMap;
HashMap<String, Integer> viewMap = new HashMap<>();
viewMap.put("자바 입문", 320);
viewMap.put("변수와 자료형", 1140);
System.out.println(viewMap.get("변수와 자료형")); // 1140
System.out.println(viewMap.containsKey("배열")); // false
같은 열쇠로 다시 put하면 값이 덮어써집니다. int가 아니라 Integer를 쓴 점도 눈여겨보십시오. 컬렉션에는 기본형을 직접 담을 수 없어 이를 감싼 클래스를 씁니다.
| 항목 | 배열 | 컬렉션(ArrayList 등) |
|---|---|---|
| 크기 | 생성 시 고정 | 자동으로 늘고 줄어듦 |
| 담을 수 있는 값 | 기본형·참조형 모두 | 참조형만 (기본형은 래퍼 클래스) |
| 추가·삭제 | 직접 옮겨야 함 | add() / remove() |
개수가 처음부터 정해져 있으면 가볍고 빠른 배열, 실행 중에 변하면 컬렉션입니다. 실무에서는 컬렉션 쪽이 훨씬 많이 쓰입니다.
핵심 정리
- 배열 인덱스 — 0부터 시작하며 반복 조건은
i < 배열.length - length vs length() — 배열은 괄호 없이, 문자열은 괄호를 붙입니다
- 2차원 배열 —
[행][열]순서, 안쪽 길이는배열[행].length - 향상된 for문 — 순서대로 훑기만 할 때 짧고 안전합니다
- ArrayList · HashMap — 크기가 변하면 ArrayList, 이름표로 찾으면 HashMap