드디어 배열! 코테에 자주 등장하는 중요한 친구이지만 정확히 모르기 때문에 더 궁금했던 배열에 대해 알아보자!
= 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것
만약 5과목의 시험 점수를 저장한다고 하자. 배열이 없다면
int Korean = 90, Math = 100, English = 80, Science = 70, Music = 50
이렇게 번거롭게 표시해줘야 한다.
그러나 우리는 배열을 통해 int[] score = new int[5]
로 간단히 표현한다.
= 단지 생성된 배열을 다루기 위한 참조변수를 위한 공간만 생성됨
= 타입[] 이름
or 타입 이름[]
(ex. int[] num)
보통은 전자의 방식으로 선언!
= 선언 후, 배열을 생성하여 데이터를 저장할 수 있는 공간을 만듦
length
는 배열의 길이를 알려주는 멤버변수int의 기본값
0으로 초기화되며, 할당 연산자 =
에 의해 배열의 주소가 int형 배열의 참조변수 num에 저장)int[] num = new int[5];
num[0] = 90;
num[1] = 80;
num[2] = 100;
num[3] = 70;
num[4] = 50;
//이 과정이 번거롭다면 아래와 같은 간편한 초기화 방법을 사용!!
int[] num = new int[]{90, 80, 100, 70, 50};
//만약 String이라면 클래스이기 때문에 new 연산자를 활용해야하지만
//""를 활용해 간략이 표현하는 것을 허용
String[] names = new String[]{"James", "Amy", "David"};
사실은 간편한 배열 초기화에 위의 방식 외에 하나가 더 있다.
// 1.
int[] num = new int[]{90, 80, 100, 70, 50};
// 2.
int[] num = {90, 80, 100, 70, 50};
//예시
int add(int[] num);
int res = add(new int[]{1,2,3,4,5});
둘 모두 같은 결과를 얻으므로 간편한 2번 방식을 쓰는 것이 좋지만,
1번 방식으로 사용해야만 하는 경우가 있다.
(ex. 선언과 초기화를 따로 해야 하는 경우, 매개변수로 배열을 받는 메서드를 호출할 때)
배열의 각 공간에 값을 저장하고 추후 그 값을 불러올 때 배열의 참조변수와 인덱스
를 활용한다.
(**인덱스 = 배열의 각 저장공간에 자동적으로 주어지는 일련의 번호
ex. 배열의 길이가 5라면 인덱스는 0~4까지
만약 이를 벗어난다면 ArrayIndexOutOfBoundsException
발생)
for(int i = 0; i < num.length; i++) {
System.out.println(num[i]);
}
사실 책에 배열을 활용한 예제들이 굉장히 많은데 코드를 짜봤다면 기본적으로 알 법한 내용이라 짜본 적 없는 신기한 코드들을 소개해볼까 한다.
//배열 인덱스의 값을 교환하는 예시
//ex. 로또 생성
public static void main(String[] args) {
int[] ball = new int[45];
//1~45까지의 값을 담는다
for(int i = 0; i < ball.length; i++) {
ball[i] = i+1;
}
int temp = 0;
int j = 0;
//배열의 첫번째 값과 임의의 인덱스 값을 100번 교환한다
for(int i = 0; i < 100; i++) {
j = (int) (Math.random()*45);
temp = ball[0];
ball[0] = ball[j];
ball[j] = temp;
}
//앞에서부터 6개의 요소를 출력한다
for(int i = 0; i < 6; i++) {
System.out.println(ball[i]+" ");
}
}
//16진수를 2진수로 변환하는 예시
public static void main(String[] args) {
char[] hex = {'C', 'A', 'F', 'E'};
String[] binary = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
String result = "";
for(int i = 0; i < hex.length; i++) {
if(hex[i]>='0' && hex[i]<='9') { //숫자일 때
result += binary[hex[i]-'0'];
} else { //A~F일 때
result += binary[hex[i]-'A'+10];
}
}
System.out.println("hex: "+new String(hex));
System.out.println("binary: "+result);
}
** 참고로 String클래스는 immutable하기 때문에 char처럼 요소 하나하나에 접근할 수 없다. 그렇기 때문에 char배열을 다루는데 필요한 다양한 메서드를 제공한다.
(ex. new String(char배열) 하면 새로운 문자열 탄생!)
** 추가적으로 ChatGPT와 함께 알아본 String이 immutable한 이유
자바에서 String이 immutable한 이유는 다음과 같습니다.
1. 보안상의 이유: 문자열 리터럴(String literal)은 자바에서 상수(Constant)로 취급됩니다. 만약 문자열이 변경 가능하다면, 문자열 리터럴이 다른 값으로 변경될 수 있으므로, 보안상의 이유로 String 객체를 immutable하게 만들어야 합니다.
2. 멀티스레딩(Thread-safe)을 보장하기 위해: 만약 문자열이 변경 가능하다면, 여러 스레드에서 동시에 문자열을 수정하면서 문제가 발생할 수 있습니다. 그러나 문자열이 immutable하면, 동기화의 문제 없이 여러 스레드에서 문자열을 공유할 수 있습니다.
3. String Pool: String Pool은 자바에서 문자열 리터럴을 재사용하는 메커니즘입니다. 문자열이 immutable하다면, 동일한 문자열이 여러 번 사용되더라도 메모리 낭비를 방지할 수 있습니다.
4. 성능 이유: 문자열이 immutable하면, 문자열이 자주 변경되는 경우에도 새로운 객체를 생성하는 비용을 절약할 수 있습니다. 대신 기존의 객체를 재활용하면 됩니다.
배열은 2차원 이상의 다차원 배열로도 사용한다. 그러나 보통은 2차원 배열까지만 사용한다.
//2차원 배열 예시
int[][] score = new int[][] {
{100, 100, 100},
{20, 20, 20},
{30, 30, 30}
};
2차원 이상의 배열이 배열의 배열
형태라는 사실을 알게 된다면 자유로운 형태의 배열
을 구성할 수 있다.
//가변 배열 예시
int[] score = new int[3][];
score[0] = new int[4];
score[1] = new int[3];
score[2] = new int[2];
(내 생각이지만 복잡한 구현이 요구되는 코테가 아니라면 요 부분은 많이 쓰일 것 같진 않다.... 하핫)
= 배열은 한번 선언하면 그 크기를 변경할 수 없어 더 많은 공간이 필요
하다면 큰 배열을 새로 선언하고 이전 배열의 내용을 복사
해야 한다.
Array.clone()
메서드 활용Arrays.copyOf()
메서드 활용Arrays.copyOfRange()
메서드 활용//clone메서드
int[] a = {1,2,3,4}
int[] b = a.clone();
//copyOf메서드
//길이도 정할 수 있음
int[] c = Arrays.copyOf(a, a.length);
//copyOfRange메서드
//시작점도 정할 수 있음
int[] d = Arrays.copyOfRange(a, 0, 2);
arraycopy()
를 사용하여 배열을 복사한다.System.arraycopy(arr1, 0, arr2, 0, arr1.length);
System.in~
메서드를 활용해 사용자로부터 값을 입력 받는 방법 외에도, 커맨드라인
을 이용하여 값을 입력받을 수 있다!!
public static void main(String[] args) {
System.out.println("매개변수의 개수: "+args.length);
for(int i = 0; i < args.length; i++) {
System.out.println("args["+i+"] = \""+args[i]+"\"");
}
}
경로~~ > java ArrayEx13 abc 123 "Hello world"
매개변수의 개수:3
args[0] = "abc";
args[1] = "123";
args[2] = "Hello world"
공백문자로 문자열을 구분하기 때문에 입력될 값에 공백이 있다면 위의 경우처럼 ""로 감싸주는 것이 좋다.
public static void main(String[] args) {
if(args.length != 3) {
System.out.println("usage: java ArrayEx15 NUM1 OP NUM2);
System.exit(0);
}
int num1 = Integer.parseInt(args[0]);
char op = args[1].charAt(0);
int num2 = Integer.parseInt(args[2]);
int result = 0;
switch(op) {
case '+':
result = num1+num2;
break;
case '-':
result = num1-num2;
break;
case '*':
result = num1*num2;
break;
case '/':
result = num1/num2;
break;
default:
System.out.println("지원되지 않는 연산입니다");
}
System.out.println("결과: "+result);
}
경로~~ > java ArrayEx13 10 + 3
결과:13
자바의 정석, 2nd Edition.
https://www.javatpoint.com/why-string-is-immutable-or-final-in-java