배열

cutiepazzipozzi·2023년 4월 20일
1

지식스택

목록 보기
21/35
post-thumbnail

드디어 배열! 코테에 자주 등장하는 중요한 친구이지만 정확히 모르기 때문에 더 궁금했던 배열에 대해 알아보자!

배열이란?

= 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것

만약 5과목의 시험 점수를 저장한다고 하자. 배열이 없다면
int Korean = 90, Math = 100, English = 80, Science = 70, Music = 50
이렇게 번거롭게 표시해줘야 한다.

그러나 우리는 배열을 통해 int[] score = new int[5]로 간단히 표현한다.

배열 선언 방식

= 단지 생성된 배열을 다루기 위한 참조변수를 위한 공간만 생성됨
= 타입[] 이름 or 타입 이름[]
(ex. int[] num)
보통은 전자의 방식으로 선언!

배열의 생성 및 초기화

= 선언 후, 배열을 생성하여 데이터를 저장할 수 있는 공간을 만듦

  • new 연산자와 함께 배열의 타입, 크기를 지정하여 생성
  • 배열 = 객체 이므로 멤버변수, 메서드를 가짐
    (ex. length는 배열의 길이를 알려주는 멤버변수
    ** 이때 배열은 생성이 되면 크기를 변경할 수 없음)
  1. 타입[] 이름(int[] num) 형태로 선언한다.
  2. num = new int[5] 생성
    연산자 new에 의해 메모리의 빈 공간에 5개의 int형 데이터를 저장할 수 있는 공간이 마련된다.
    (int의 기본값 0으로 초기화되며, 할당 연산자 =에 의해 배열의 주소가 int형 배열의 참조변수 num에 저장)
    - 만약 여기서 String타입으로 배열을 선언하면 String은 참조변수이기 때문에 null로 초기화된다.
    - 데이터를 저장하는 공간이 생성되면, 이 배열의 주소값은 배열[0], 즉 첫번째 인덱스의 주솟값이다.
  • 생성과 동시에 기본값으로 초기화되지만, 원하는 값으로 초기화 하고 싶다면 직접 인덱스에 접근해 값을 지정한다.
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문을 활용하는데, 이때 조건문에는 배열의 길이 length를 활용하는 것이 좋다.
    (length는 배열의 크기가 변경되면 자동적으로 그 크기를 갖기 때문에)
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차원 배열의 선언

  1. 타입[][] 변수명
  2. 타입 변수명[][]
  3. 타입[] 변수명[]
//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];

(내 생각이지만 복잡한 구현이 요구되는 코테가 아니라면 요 부분은 많이 쓰일 것 같진 않다.... 하핫)

배열의 복사

= 배열은 한번 선언하면 그 크기를 변경할 수 없어 더 많은 공간이 필요하다면 큰 배열을 새로 선언하고 이전 배열의 내용을 복사해야 한다.

깊은 복사

  • 새로운 메모리 공간에 값을 복사하는 것
    (그래서 메모리 측면에서 보면 비효율적일수도 있음)
  1. Array.clone()메서드 활용
  2. Arrays.copyOf()메서드 활용
  3. 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);

얕은 복사

  • 한쪽이 수정하게 되면 다른 한쪽에도 영향이 미쳐 수정됨
    (해당 객체와 인스턴스 변수까지 복사)
    System 클래스의 arraycopy()를 사용하여 배열을 복사한다.
    이는 배열에 저장되어 있는 값만 복사하므로 참조변수 배열이라면 단지 주소값만을 복사한다.
    (원래 배열의 요소와 같은 객체를 참조)
    System.arraycopy(arr1, 0, arr2, 0, arr1.length);
    -> 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
  • (++) javax.swing 라이브러리의 JOptionPane 클래스를 활용(showInputDialog메서드)하면 입력창을 생성할 수 있다.

참고

자바의 정석, 2nd Edition.
https://www.javatpoint.com/why-string-is-immutable-or-final-in-java

profile
노션에서 자라는 중 (●'◡'●)

0개의 댓글