지금까지는 단순한 변수에 값을 할당하는 방식으로 데이터를 관리했었다.
하지만 여러 비슷한 변수들이 필요한 경우, 변수의 양이 굉장히 많은 경우 비효율적인 상황이 생길 수 있다.
public class Array1 {
public static void main(String[] args) {
int student1 = 90;
int student2 = 80;
int student3 = 70;
int student4 = 60;
int student5 = 50;
//학생을 한 명 더 추가한다면
int student6 = 40;
//반복문으로 해결할 수 없나?
for(int i=1; i <=6; i++) {
System.out.println("학생" + i + "점수" + student1);
}
//변수명까지 i를 활용할 수는 없다..
System.out.println("학생1 점수: "+ student1);
System.out.println("학생2 점수: "+ student2);
System.out.println("학생3 점수: "+ student3);
System.out.println("학생4 점수: "+ student4);
System.out.println("학생5 점수: "+ student5);
System.out.println("학생6 점수: "+ student6);
}
}
위와 같은 상황에서 배열을 활용하면 더욱 효율적인 코드를 작성할 수 있다.
배열은 같은 타입의 변수를 하나로 묶어둔 것이다.
(여러 타입의 변수를 담으려면 ArrayList를 사용해야 한다. Array는 전부 같은 타입의 요소만 담을 수 있다.)
기본형과 참조형
기본형(Primitive Type)
int, long, double, boolean처럼 변수에 사용할 값을 직접 넣는 데이터 타입.
기본형은 데이터의 사이즈가 명확하게 정해져 있다. (int는 4바이트, double은 8바이트)
참조형(Reference Type)
int[] students와 같이 데이터에 접근하기 위한 참조(주소)를 저장하는 데이터 타입 (객체, 클래스를 담는 변수)
배열은 왜 참조를 해야 할까?
기본타입은 선언과 동시에 사이즈가 정해지기 때문에 정적 할당이 이루어진다. (컴파일 타임)
(그렇기 때문에 더 빠르고 효율적인 메모리 사용이 가능하다.)
하지만 배열의 사이즈는 바뀔 수 있기 때문에 동적 메모리 할당의 가능성이 있다. (런 타임)
(ex. Scanner를 통해 배열의 사이즈를 프로세스에서 받는 경우)
즉 참조형을 활용하면 더 유연한 메모리 할당이 가능한 것이다. (new 키워드를 통한 객체 인스턴스 생성)
1차원 배열 초기화와 인덱싱
public static void main(String[] args) {
int[] students; //배열 주소를 담을 변수 선언
students = new int[3];
// students = new int[]; 배열의 사이즈를 누락한 경우 array dimension missing
// 배열의 크기 만큼 메모리 공간을 확보(int의 경우 4byte * 3)
// 배열 생성 후 배열의 참조값(주소)가 students 변수에 담긴다.
// [I@3f99bd52 -- 정수 배열, 16진법 표기
//3개의 int공간이 생성, 0으로 *자동 초기화
//숫자는 0, boolean은 false, String은 null로 자동 초기화
//배열의 사이즈를 벗어나는 경우_Swift에서의 index out of range
// Index 5 out of bounds for length 5 at array.
//인덱싱을 통한 배열 값 변경
students[0] = 90;
//[I@3f99bd52 참조값을 통해 실제 배열에 접근, 인덱스를 사용해서 해당 위치 요소에 접근 후 값 대입
students[1] = 80;
students[2] = 70;
System.out.println("학생1 점수: "+ students[0]);
System.out.println("학생2 점수: "+ students[1]);
System.out.println("학생3 점수: "+ students[2]);
System.out.println(students);
}
public static void main(String[] args) {
int[] students = new int[5];
int arraySize = students.length;
// int[] students = new int[]{90, 80, 70, 60, 50}; //배열 생성과 초기화
// int[] students = {90, 80, 70, 60, 50}; // 타입 추론 초기화
// 왜 중괄호를 쓰는 지 궁금했지만 그냥 java 문법인 것 같다.
// 사이즈 5의 배열에 3개의 초기값을 주면 나머지는 0으로 자동 초기화 되나 싶었지만..
// array creation with both dimension expression and initialization is illegal
// int[] testArray = new int[5]{1,2,3};
for (int i = 0; i < students.length; i++) {
students[i] = 100 - (10 * (i + 1));
}
for (int i = 0; i < students.length; i++) {
System.out.println("학생 " + (i + 1) + " 점수 = " + students[i]);
}
System.out.println(students);
}
2차원 배열
row(행) column(열)
public static void main(String[] args) {
//2 x 3 배열
int[][] arr = new int[2][3];
// 0 0 0
// 0 0 0 이렇게 초기화
// [[1, 2, 3], [4, 5, 6]] 파이썬 문법으로 본다면
arr[0][0] = 1; //0행 0열
arr[0][1] = 2; //0행 1열
arr[0][2] = 3; //0행 2열
arr[1][0] = 4; //1행 0열
arr[1][1] = 5; //1행 1열
arr[1][2] = 6; //1행 2열
// 1 2 3
// 4 5 6
System.out.print(arr[0][0] + " ");
System.out.print(arr[0][1] + " ");
System.out.println(arr[0][2] + " ");
System.out.print(arr[1][0] + " ");
System.out.print(arr[1][1] + " ");
System.out.print(arr[1][2] + " ");
}
초기값을 통한 초기화, 2중 for문을 활용한 개선 (배열과 기본적으로는 동일하다)
public static void main(String[] args) {
int[][] arr = new int[2][3];
int row = arr.length;
// int[][] arr = new int[][] {
// {1, 2, 3},
// {4, 5, 6}
// };
// int[][] arr = {
// {1, 2, 3},
// {4, 5, 6}
// };
for (int i = 0; i < row; i++) {
for (int j = 0; j < arr[i].length; j++) {
arr[i][j] = (i * 3) + (j + 1);
}
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
+ 3차원 배열의 경우에는 면, 행, 열로 생각할 수 있다.
int[][][] triple = new int[3][3][3];
Enhanced For (For Each)
인덱스를 사용하지 않고, 종료 조건도 없이 배열의 요소를 전부 탐색할 수 있는 편리한 반복문.
하지만 인덱싱이 필요한 경우에는 일반 반복문을 사용하는 편이 효율적이다.
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};
//단축키 iter
//일반 for문
for (int i = 0; i < numbers.length; i++) {
System.out.print(numbers[i] + " ");
}
System.out.println();
// for-each 배열의 요소를 순차적으로 순회한다.
// numbers 배열의 각 요소에 대한 값의 복사본이 number로
for (int number : numbers) {
System.out.print(number + " ");
}
}
Scanner, Array, Switch 활용 예시
보통 객체에 담아서 데이터를 관리하겠지만, 단일 배열을 활용한 예시
import java.util.Scanner;
// 상품 등록: 상품 이름과 가격을 입력받아 저장.
// 상품 목록: 지금까지 등록한 모든 상품의 목록 출력
// 첫 화면에서 사용자에게 세 가지 선택 제시 1. 상품 등록, 2. 상품 목록, 3.종료
// 1번은 사용자로부터 상품 이름과 가격을 입력받아 배열에 저장한다.
// 2번은 배열에 저장된 모든 상품을 출력한다.
// 3. 종료를 선택하면 프로그램 종료
// 상품은 최대 10개까지 등록할 수 있다.
public class ArrayEx8 {
public static void main(String[] args) {
boolean active = true;
Scanner scanner = new Scanner(System.in);
int maxProducts = 3;
String[] productNames = new String[maxProducts];
int[] productPrice = new int[maxProducts];
int productCount = 0;
while (active) {
System.out.print("1. 상품 등록 | 2. 상품 목록 | 3. 종료\n메뉴를 선택하세요: ");
//숫자만 입력한다는 가정
int option = scanner.nextInt();
//입력 버퍼 비우기 \n
scanner.nextLine();
switch (option) {
case 1:
if (productCount >= maxProducts) {
System.out.println("더 이상 상품을 등록할 수 없습니다.");
continue;
// break;
}
System.out.print("상품 이름을 입력하세요: ");
productNames[productCount] = scanner.next();
System.out.print("상품 가격을 입력하세요: ");
productPrice[productCount] = scanner.nextInt();
productCount++;
break;
case 2:
if (productCount == 0) {
System.out.println("등록된 상품이 없습니다.");
continue;
}
for (int i = 0; i < productCount; i++) {
System.out.printf("%s : %d 원\n", productNames[i], productPrice[i]);
}
case 3:
System.out.println("프로그램을 종료합니다.");
active = false;
default:
System.out.println("잘못된 메뉴를 입력하셨습니다.");
break;
}
}
}
}
학습 출처
'JAVA > Java Start' 카테고리의 다른 글
9. 메서드(method) (0) | 2024.02.10 |
---|---|
7. Scanner 유저인풋 (0) | 2024.01.24 |
6. 스코프(Scope), 타입캐스팅(Type Casting)_형변환 (0) | 2024.01.21 |
5. 반복문 (while, for, continue/break) (0) | 2024.01.20 |
4. 조건문(if, switch, 삼항 연산자) (0) | 2024.01.15 |