5장. 배열과 문자열
배열의 개념
배열이란?
배열(Array)은 같은 타입의 데이터를 연속된 메모리 공간에 저장하는 자료구조입니다. 배열을 사용하면 여러 개의 변수를 하나의 이름으로 관리할 수 있습니다.
배열의 특징
- 같은 타입의 데이터만 저장: int 배열에는 int만, String 배열에는 String만 저장
- 연속된 메모리 공간: 배열 요소들이 메모리에 연속적으로 저장됨
- 인덱스(Index)로 접근: 0부터 시작하는 인덱스로 각 요소에 접근
- 고정된 크기: 배열을 생성할 때 크기가 결정되며, 이후 변경 불가
배열의 장점
- 여러 데이터를 효율적으로 관리
- 반복문과 함께 사용하여 코드 간결화
- 빠른 접근 속도 (인덱스로 직접 접근)
배열의 단점
- 크기가 고정되어 있어 유연성 부족
- 크기 변경 시 새로운 배열 생성 필요
1차원 배열
배열 선언과 초기화
방법 1: 선언 후 초기화
// 배열 선언
int[] numbers; // 또는 int numbers[];
// 배열 생성 및 초기화
numbers = new int[5]; // 크기가 5인 배열 생성
// 값 할당
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
방법 2: 선언과 동시에 초기화
// 배열 선언과 동시에 값 할당
int[] numbers = {10, 20, 30, 40, 50};
// 또는
int[] numbers = new int[]{10, 20, 30, 40, 50};
방법 3: 선언과 생성 분리
int[] numbers;
numbers = new int[5]; // 기본값으로 초기화 (int는 0)
배열의 기본값
배열을 생성하면 각 요소는 해당 타입의 기본값으로 자동 초기화됩니다.
| 타입 | 기본값 |
|---|---|
byte, short, int, long |
0 |
float, double |
0.0 |
char |
'\u0000' (null 문자) |
boolean |
false |
| 참조 타입 | null |
배열 접근
int[] numbers = {10, 20, 30, 40, 50};
// 인덱스로 접근 (0부터 시작)
System.out.println(numbers[0]); // 10
System.out.println(numbers[1]); // 20
System.out.println(numbers[4]); // 50
// 배열 길이
System.out.println(numbers.length); // 5
// 마지막 요소 접근
System.out.println(numbers[numbers.length - 1]); // 50
배열과 반복문
배열은 반복문과 함께 사용하면 매우 유용합니다.
int[] numbers = {10, 20, 30, 40, 50};
// for 문으로 배열 순회
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
// 향상된 for 문 (for-each)
for (int num : numbers) {
System.out.println(num);
}
향상된 for 문 (Enhanced for loop)
Java 5부터 제공되는 문법으로, 배열의 모든 요소를 순회할 때 사용합니다.
// 형식: for (타입 변수명 : 배열명)
int[] numbers = {10, 20, 30, 40, 50};
for (int num : numbers) {
System.out.println(num);
}
// String 배열
String[] names = {"홍길동", "김철수", "이영희"};
for (String name : names) {
System.out.println(name);
}
장점: 간결하고 안전 (인덱스 오류 방지)
단점: 인덱스 정보가 필요할 때는 사용 불가
2차원 배열
2차원 배열이란?
2차원 배열은 배열의 배열입니다. 행과 열로 구성된 표 형태의 데이터를 저장할 수 있습니다.
2차원 배열 선언과 초기화
방법 1: 선언 후 초기화
// 배열 선언
int[][] matrix; // 또는 int matrix[][];
// 배열 생성
matrix = new int[3][4]; // 3행 4열 배열
// 값 할당
matrix[0][0] = 1;
matrix[0][1] = 2;
matrix[1][0] = 3;
방법 2: 선언과 동시에 초기화
// 2차원 배열 초기화
int[][] matrix = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 또는
int[][] matrix = new int[][]{
{1, 2, 3},
{4, 5, 6}
};
2차원 배열 접근
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 특정 요소 접근
System.out.println(matrix[0][0]); // 1 (첫 번째 행, 첫 번째 열)
System.out.println(matrix[1][2]); // 6 (두 번째 행, 세 번째 열)
// 배열 크기
System.out.println(matrix.length); // 3 (행의 개수)
System.out.println(matrix[0].length); // 3 (첫 번째 행의 열 개수)
2차원 배열과 반복문
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// 이중 for 문으로 순회
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
// 향상된 for 문 사용
for (int[] row : matrix) {
for (int num : row) {
System.out.print(num + " ");
}
System.out.println();
}
가변 배열 (Jagged Array)
각 행의 길이가 다른 배열을 만들 수 있습니다.
// 가변 배열 선언
int[][] jagged = new int[3][];
jagged[0] = new int[2]; // 첫 번째 행은 2개
jagged[1] = new int[4]; // 두 번째 행은 4개
jagged[2] = new int[3]; // 세 번째 행은 3개
// 초기화
int[][] jagged = {
{1, 2},
{3, 4, 5, 6},
{7, 8, 9}
};
배열 활용 예제
예제 1: 배열의 최댓값, 최솟값 찾기
int[] numbers = {10, 5, 8, 20, 3, 15};
int max = numbers[0];
int min = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > max) {
max = numbers[i];
}
if (numbers[i] < min) {
min = numbers[i];
}
}
System.out.println("최댓값: " + max);
System.out.println("최솟값: " + min);
예제 2: 배열 요소 합계와 평균
int[] numbers = {10, 20, 30, 40, 50};
int sum = 0;
for (int num : numbers) {
sum += num;
}
double average = (double) sum / numbers.length;
System.out.println("합계: " + sum);
System.out.println("평균: " + average);
예제 3: 배열 요소 검색
int[] numbers = {10, 20, 30, 40, 50};
int target = 30;
boolean found = false;
int index = -1;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == target) {
found = true;
index = i;
break;
}
}
if (found) {
System.out.println(target + "을(를) 인덱스 " + index + "에서 찾았습니다.");
} else {
System.out.println(target + "을(를) 찾을 수 없습니다.");
}
예제 4: 배열 복사
int[] original = {1, 2, 3, 4, 5};
// 방법 1: 반복문 사용
int[] copy1 = new int[original.length];
for (int i = 0; i < original.length; i++) {
copy1[i] = original[i];
}
// 방법 2: System.arraycopy() 사용
int[] copy2 = new int[original.length];
System.arraycopy(original, 0, copy2, 0, original.length);
// 방법 3: clone() 메서드 사용
int[] copy3 = original.clone();
예제 5: 배열 역순 출력
int[] numbers = {1, 2, 3, 4, 5};
// 역순으로 출력
for (int i = numbers.length - 1; i >= 0; i--) {
System.out.print(numbers[i] + " ");
}
// 출력: 5 4 3 2 1
문자열 클래스 (String)
String이란?
String은 Java에서 문자열을 다루는 클래스입니다. String은 참조 타입이지만, 기본 타입처럼 사용할 수 있도록 특별히 설계되었습니다.
String의 특징
- 불변(Immutable): String 객체는 한 번 생성되면 변경할 수 없음
- 문자열 리터럴: 같은 문자열 리터럴은 같은 객체를 참조
- 문자열 풀(String Pool): JVM이 문자열 리터럴을 관리하는 특별한 메모리 영역
String 생성 방법
방법 1: 문자열 리터럴 (가장 일반적)
String str1 = "Hello";
String str2 = "Hello"; // str1과 같은 객체 참조
방법 2: new 연산자 사용
String str3 = new String("Hello");
String str4 = new String("Hello"); // str3와 다른 객체
방법 3: char 배열로부터 생성
char[] chars = {'H', 'e', 'l', 'l', 'o'};
String str5 = new String(chars);
String 비교
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
// == 연산자: 참조 비교
System.out.println(str1 == str2); // true (같은 객체)
System.out.println(str1 == str3); // false (다른 객체)
// equals() 메서드: 내용 비교 (권장)
System.out.println(str1.equals(str2)); // true
System.out.println(str1.equals(str3)); // true
주의: 문자열 비교는 항상 equals() 메서드를 사용해야 합니다!
String 연결 (Concatenation)
// + 연산자 사용
String firstName = "홍";
String lastName = "길동";
String fullName = firstName + " " + lastName; // "홍 길동"
// += 연산자
String message = "Hello";
message += " World"; // "Hello World"
// concat() 메서드
String str = "Hello";
str = str.concat(" World"); // "Hello World"
문자열 주요 메서드
길이와 빈 문자열 확인
String str = "Hello";
// length(): 문자열 길이
int len = str.length(); // 5
// isEmpty(): 빈 문자열 확인
boolean empty = str.isEmpty(); // false
String emptyStr = "";
boolean isEmp = emptyStr.isEmpty(); // true
문자열 검색
String str = "Hello World";
// charAt(index): 특정 위치의 문자
char ch = str.charAt(0); // 'H'
char ch2 = str.charAt(6); // 'W'
// indexOf(): 문자열이나 문자의 첫 번째 위치
int index1 = str.indexOf('o'); // 4
int index2 = str.indexOf("World"); // 6
int index3 = str.indexOf('x'); // -1 (없으면 -1 반환)
// lastIndexOf(): 마지막 위치
int lastIndex = str.lastIndexOf('o'); // 7
// contains(): 포함 여부
boolean hasHello = str.contains("Hello"); // true
문자열 추출
String str = "Hello World";
// substring(): 부분 문자열 추출
String sub1 = str.substring(0, 5); // "Hello" (0부터 5 전까지)
String sub2 = str.substring(6); // "World" (6부터 끝까지)
// split(): 문자열 분리
String[] parts = str.split(" "); // {"Hello", "World"}
String date = "2024-01-15";
String[] dateParts = date.split("-"); // {"2024", "01", "15"}
문자열 변환
String str = "Hello World";
// toUpperCase(): 대문자로 변환
String upper = str.toUpperCase(); // "HELLO WORLD"
// toLowerCase(): 소문자로 변환
String lower = str.toLowerCase(); // "hello world"
// trim(): 앞뒤 공백 제거
String withSpaces = " Hello ";
String trimmed = withSpaces.trim(); // "Hello"
// replace(): 문자열 치환
String replaced = str.replace("World", "Java"); // "Hello Java"
String replaced2 = str.replace('l', 'L'); // "HeLLo WorLd"
문자열 비교
String str1 = "apple";
String str2 = "Apple";
String str3 = "banana";
// equals(): 대소문자 구분 비교
boolean eq1 = str1.equals(str2); // false
// equalsIgnoreCase(): 대소문자 무시 비교
boolean eq2 = str1.equalsIgnoreCase(str2); // true
// compareTo(): 사전식 비교
int cmp1 = str1.compareTo(str3); // 음수 (apple < banana)
int cmp2 = str3.compareTo(str1); // 양수 (banana > apple)
int cmp3 = str1.compareTo(str1); // 0 (같음)
// startsWith(): 접두사 확인
boolean starts = str1.startsWith("app"); // true
// endsWith(): 접미사 확인
boolean ends = str1.endsWith("le"); // true
문자열 변환 (다른 타입으로)
// 숫자 문자열을 숫자로 변환
String numStr = "123";
int num = Integer.parseInt(numStr); // 123
double dNum = Double.parseDouble("3.14"); // 3.14
// 숫자를 문자열로 변환
int number = 123;
String str1 = String.valueOf(number); // "123"
String str2 = Integer.toString(number); // "123"
String str3 = number + ""; // "123" (간단하지만 비효율적)
StringBuilder와 StringBuffer
String은 불변이므로 문자열을 자주 변경할 때는 StringBuilder나 StringBuffer를 사용하는 것이 효율적입니다.
// StringBuilder 사용 (단일 스레드 환경)
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(" ");
sb.append("World");
String result = sb.toString(); // "Hello World"
// 체이닝 가능
StringBuilder sb2 = new StringBuilder();
String result2 = sb2.append("Hello")
.append(" ")
.append("World")
.toString();
배열과 문자열 종합 예제
public class ArrayStringExample {
public static void main(String[] args) {
// 배열 예제
int[] numbers = {10, 20, 30, 40, 50};
// 합계 계산
int sum = 0;
for (int num : numbers) {
sum += num;
}
System.out.println("합계: " + sum);
// 문자열 예제
String text = "Hello World";
// 대문자로 변환
String upper = text.toUpperCase();
System.out.println("대문자: " + upper);
// 단어 분리
String[] words = text.split(" ");
for (String word : words) {
System.out.println(word);
}
}
}
연습 문제
배열 기본
- 10개의 정수를 저장하는 배열을 만들고, 1부터 10까지의 값을 저장한 후 출력하세요.
배열 최댓값/최솟값
- 정수 배열에서 최댓값과 최솟값을 찾는 프로그램을 작성하세요.
2차원 배열
- 3x3 행렬을 만들고, 1부터 9까지의 값을 저장한 후 출력하세요.
문자열 처리
- 사용자 이름을 입력받아 대문자로 변환하고, 이름의 길이를 출력하는 프로그램을 작성하세요.
문자열 검색
- 문장에서 특정 단어가 몇 번 나타나는지 세는 프로그램을 작성하세요.
배열과 문자열 조합
- 여러 개의 이름을 배열에 저장하고, 각 이름의 길이를 출력하는 프로그램을 작성하세요.
다음 장 예고
다음 장에서는 메서드(Method)를 사용하여 코드를 재사용하고 구조화하는 방법을 학습합니다.
'BackEnd > Java' 카테고리의 다른 글
| 7장. 객체지향 프로그래밍(OOP) 기초 (0) | 2026.01.01 |
|---|---|
| 6장. 메서드(Method) (0) | 2025.12.31 |
| 4장. 제어문 (0) | 2025.12.30 |
| 3장. 연산자 (0) | 2025.12.29 |
| 2장. 변수와 자료형 (0) | 2025.12.28 |