본문 바로가기
프로그래밍/JAVA

초보 자바 프로그래밍(15) - 배열 (Arrays)

by 머니테크리더 2023. 5. 1.
반응형

자바 배열 대표 이미지
자바 배열 대표 이미지

🔖 INDEX

     

     

    배열(Array)은 프로그래밍에서 일련의 동일한 데이터 타입의 요소들을 연속적으로 저장할 수 있는 자료구조입니다. 자바에서 배열은 객체로 취급되며, 배열의 각 요소는 인덱스를 통해 참조할 수 있습니다. 인덱스는 0부터 시작하여, 배열의 길이보다 1 작은 정수로 종료됩니다. 배열은 선언과 동시에 길이가 고정되며, 이후에는 변경할 수 없습니다.

     

    배열을 사용하는 이유

    배열은 다음과 같은 이유로 프로그래밍에서 필수적인 자료구조입니다.

    1. 데이터 관리의 효율성
      • 배열을 사용하면 동일한 데이터 타입의 여러 값을 하나의 변수로 관리할 수 있어 코드의 가독성과 관리가 편리해집니다. 예를 들어, 학생들의 성적을 관리할 때 배열을 사용하면 각각의 변수를 선언하지 않고, 하나의 배열로 성적을 저장하고 처리할 수 있습니다.
      • 배열은 데이터의 순서를 유지하며 저장하기 때문에, 데이터 간의 상대적 위치를 쉽게 파악할 수 있습니다.
    2. 성능 향상
      • 배열은 메모리 상에 연속적인 공간에 요소를 저장하므로, CPU 캐시를 효율적으로 활용할 수 있어 성능이 향상됩니다. 이로 인해 배열 기반의 알고리즘은 다른 자료구조에 비해 속도가 빠른 경우가 많습니다.
    3. 다양한 알고리즘 구현
      • 배열은 정렬, 검색, 행렬 연산 등 다양한 알고리즘을 구현하는데 사용되며, 데이터를 효율적으로 처리할 수 있게 해줍니다. 예를 들어, 버블 정렬, 이진 검색 등의 알고리즘은 배열을 기반으로 동작합니다.
      • 또한, 배열은 다양한 자료구조(스택, 큐, 힙 등)의 기반이 되기도 합니다.
    4. 다차원 데이터 구조
      • 배열은 다차원 데이터를 표현하기 위해 사용될 수 있으며, 이미지 처리, 그래프 등 다양한 분야에서 활용되고 있습니다. 예를 들어, 2차원 배열을 사용해 행렬을 표현하거나, 3차원 배열을 사용해 3D 공간 데이터를 저장할 수 있습니다.
      • 게임 개발, 과학 계산, GIS 등 다양한 분야에서 다차원 배열은 필수적인 도구로 사용됩니다. ​

    이러한 이유로 배열은 프로그래밍에서 매우 중요한 역할을 하며, 자바에서도 다양한 상황에서 배열을 활용할 수 있습니다.

     

     

    배열 선언 및 초기화

    배열을 사용하기 위해서는 먼저 배열을 선언해야 합니다. 배열 선언은 데이터 타입 뒤에 대괄호([])를 추가하여 진행합니다. 예를 들어, 정수형 배열을 선언하려면 다음과 같이 작성합니다.

    int[] numbers;

     

    배열을 선언한 후에는 초기화 과정을 거쳐 메모리에 할당해야 합니다. 초기화는 new 키워드를 사용하여 진행하며, 배열의 크기를 지정해야 합니다.

    int[] numbers = new int[5];

    이 코드는 크기가 5인 정수형 배열을 선언하고 초기화한 것입니다. 배열의 요소는 기본값으로 초기화됩니다(정수형 배열의 경우 0으로 초기화).

     

    배열 선언 및 초기화 시 주의해야 할 점은 다음과 같습니다.

     

    1. 적절한 데이터 타입 선택 : 배열을 선언할 때 사용할 데이터 타입을 명확하게 선택해야 합니다. 데이터 타입에 따라 배열이 저장할 수 있는 값의 범위와 메모리 사용량이 달라질 수 있습니다. 예를 들어, 큰 정수 값을 저장할 때는 int 대신 long을 사용하거나, 소수점 값을 저장할 때는 float 대신 double을 사용하는 등 상황에 맞는 데이터 타입을 선택하세요.

     

    2. 배열 크기 지정 : 배열을 초기화할 때 배열의 크기를 명시해야 합니다. 배열의 크기는 양의 정수 값이어야 하며, 음수 값을 지정하면 'NegativeArraySizeException'이 발생합니다. 또한, 배열의 크기가 너무 큰 경우 메모리 부족으로 인해 'OutOfMemoryError'가 발생할 수 있으므로, 적절한 크기를 지정해야 합니다.

     

    3. 배열 초기화 : 배열을 생성하면 기본값으로 초기화되므로, 명시적으로 초기화가 필요한 경우 요소 값을 설정해야 합니다. 예를 들어, 정수 배열의 경우 기본값은 0이지만, 다른 초기값이 필요한 경우 배열의 각 요소에 값을 할당해야 합니다. 또한, 참조형 배열의 경우 각 요소에 대한 객체 생성을 잊지 않도록 주의해야 합니다.

    MyClass[] myObjects = new MyClass[5];
    for (int i = 0; i < myObjects.length; i++) {
        myObjects[i] = new MyClass(); // 객체 생성 후 배열 요소에 할당
    }

     

    4. 배열 선언과 초기화를 동시에 수행 : 배열 선언과 초기화를 동시에 수행하려면 중괄호({})를 사용하여 배열의 요소 값을 지정할 수 있습니다. 이 방법을 사용하면 배열의 길이를 따로 지정할 필요가 없으며, 컴파일러가 자동으로 배열의 길이를 결정합니다.

    int[] numbers = {1, 2, 3, 4, 5};

     

    5. 로컬 배열 초기화 : 메서드 내에서 선언된 로컬 배열은 자동으로 초기화되지 않습니다. 따라서 로컬 배열을 사용하기 전에 명시적으로 초기화해야 합니다. 이렇게 하지 않으면 컴파일러가 초기화되지 않은 변수 사용으로 오류를 발생시킬 수 있습니다. ​

     

    6. 배열 참조 확인 : 참조형 배열을 사용할 때, 배열 요소가 null을 참조하고 있는지 확인해야 합니다. null 참조를 통해 객체의 속성이나 메서드에 접근하려고 하면 'NullPointerException'이 발생합니다. 따라서 배열 요소를 사용하기 전에 null 체크를 수행하세요.

    if (myObjects[i] != null) {
        // 배열 요소를 사용하는 코드
    }

     

    7. 배열 복사 : 배열을 복사할 때는 System.arraycopy() 메서드를 사용하거나, 반복문을 사용하여 요소를 복사하는 것이 좋습니다. 단순히 배열 참조를 다른 변수에 할당하는 것은 원본 배열과 복사된 배열이 동일한 메모리 영역을 참조하게 되므로, 원본 데이터의 변경이 복사된 배열에도 영향을 미칩니다.

     

    이러한 주의점들을 염두에 두고 배열을 선언하고 초기화하면, 자바 프로그래밍에서 배열을 안전하게 사용할 수 있으며, 데이터 관리를 더 효율적으로 수행할 수 있습니다.

     

     

    배열 데이터 접근

    배열에서 데이터에 접근하려면 인덱스를 사용합니다. 인덱스는 0부터 시작하여 배열의 길이보다 1 작은 정수로 종료됩니다. 배열 요소에 값을 할당하거나 값을 읽어오려면 대괄호 안에 인덱스를 작성하면 됩니다.

    numbers[0] = 10; // 배열의 첫 번째 요소에 10 할당
    int value = numbers[0]; // 배열의 첫 번째 요소 값을 value 변수에 저장

     

    배열 요소에 접근할 때 주의해야 할 몇 가지 사항이 있습니다. 이러한 주의점들을 이해하고 적절히 대처하면 배열을 안전하게 사용할 수 있습니다.

     

    1. 인덱스 범위 확인 : 배열 요소에 접근할 때 인덱스 범위를 벗어나지 않도록 주의해야 합니다. 인덱스는 0부터 시작하여 배열의 길이보다 1 작은 정수로 종료되므로, 이 범위를 벗어나면 'ArrayIndexOutOfBoundsException'이 발생합니다. 인덱스를 사용할 때 항상 배열의 길이를 확인하거나, 반복문의 범위를 배열의 길이에 맞춰 설정하세요.

    for (int i = 0; i < arr.length; i++) {
        // 안전하게 배열 요소에 접근
    }

     

    2. null 참조 확인 : 참조형 배열을 사용할 때, 배열 요소가 null을 참조하고 있는지 확인해야 합니다. null 참조를 통해 객체의 속성이나 메서드에 접근하려고 하면 'NullPointerException'이 발생합니다. 따라서 배열 요소를 사용하기 전에 null 체크를 수행하세요.

    if (myObjects[i] != null) {
        // 배열 요소를 사용하는 코드
    }

     

    3. 요소 타입 변환 : 배열 요소의 타입을 변환하려면 캐스팅 연산자를 사용해야 합니다. 예를 들어, Object 배열에서 특정 클래스의 객체를 가져오려면 적절한 클래스로 캐스팅해야 합니다. 이때, 캐스팅하는 클래스와 실제 객체의 타입이 일치하지 않으면 'ClassCastException'이 발생합니다. 이를 방지하기 위해 instanceof 연산자를 사용하여 객체의 타입을 확인한 후 캐스팅하세요.

    if (objects[i] instanceof MyClass) {
        MyClass myObject = (MyClass) objects[i];
        // myObject 사용
    }

     

    이러한 주의점들을 염두에 두고 배열 요소에 접근하면, 자바 프로그래밍에서 배열을 안전하게 사용하고 예기치 않은 오류를 방지할 수 있습니다. 또한, 코드의 가독성과 유지 관리성을 높이는 데 도움이 됩니다.

     

    배열의 길이 및 크기 조절

    배열의 길이는 length 속성을 사용하여 얻을 수 있습니다. 예를 들어, numbers 배열의 길이를 구하려면 다음과 같이 작성합니다.

    int length = numbers.length;

     

    배열은 선언과 동시에 길이가 고정되며, 이후에는 변경할 수 없습니다. 배열의 크기를 변경하려면 새로운 배열을 생성하고 기존 배열의 데이터를 복사해야 합니다. 이 경우, System.arraycopy() 메서드를 사용할 수 있습니다.

    int[] newNumbers = new int[10];
    System.arraycopy(numbers, 0, newNumbers, 0, numbers.length);

    위 코드는 numbers 배열의 데이터를 크기가 10인 newNumbers 배열로 복사하는 예제입니다. 이렇게 하면 newNumbers 배열에 numbers 배열의 데이터가 복사되며, 배열의 크기를 변경할 수 있습니다.

     

    배열의 길이와 크기 조절 시 주의해야 할 점은 다음과 같습니다: ​

     

    1. 고정 길이 : 배열은 생성 시 지정된 길이를 변경할 수 없는 고정 길이를 가집니다. 배열의 길이를 늘리거나 줄일 수 없으므로, 배열의 크기가 변경될 가능성이 있는 경우 미리 고려해야 합니다. 배열의 길이가 자주 변경되는 경우, 동적 배열 구조(예: ArrayList)를 사용하는 것이 좋습니다. ​

     

    2. 새 배열 생성 및 복사 : 배열의 길이를 변경하려면 새로운 배열을 생성하고 기존 배열의 데이터를 복사해야 합니다. 이 작업은 리소스를 소모하고, 성능 저하를 가져올 수 있으므로, 배열 크기 조절이 빈번하지 않은 경우에만 사용하는 것이 좋습니다

    int[] newArray = new int[newSize];
    System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));

     

    3. 배열 요소 재정렬 : 배열의 길이를 줄이면서 요소를 삭제할 때, 해당 요소를 제거한 후 배열의 요소를 재정렬해야 할 수도 있습니다. 이렇게 하려면 요소 삭제 후 남은 요소들을 앞으로 이동시켜야 합니다. 이 작업은 추가적인 계산 비용이 발생하므로, 삭제 및 추가 작업이 빈번한 경우 LinkedList와 같은 다른 자료 구조를 고려해 보세요. ​

     

    4. 메모리 누수 : 배열의 길이를 줄일 때, 참조형 요소가 새 배열로 복사되지 않은 경우 메모리 누수가 발생할 수 있습니다. 기존 배열에서 참조를 제거하지 않으면, 가비지 컬렉터가 해당 객체를 회수하지 못하게 됩니다. 따라서 참조형 배열에서 길이를 줄일 때는, 기존 배열의 참조를 명시적으로 제거해야 합니다.

    for (int i = newSize; i < oldArray.length; i++) {
        oldArray[i] = null;
    }

     

    5. 동시성 문제 : 배열의 크기를 조절하는 동안 다른 스레드에서 해당 배열에 접근하려고 하면 동시성 문제가 발생할 수 있습니다. 이러한 문제를 해결하기 위해 적절한 동기화 메커니즘을 적용해야 합니다. 동기화 블록(synchronized)을 사용하거나, java.util.concurrent 패키지의 동시성 제어 도구를 활용할 수 있습니다. ​

     

    6. 배열 크기에 대한 예측 : 배열의 크기가 변경되는 경우, 가능한 한 정확한 크기를 예측하려고 노력하세요. 배열 크기가 너무 작으면 자주 조절해야 하는 문제가 발생할 수 있으며, 너무 크면 불필요한 메모리 낭비가 발생할 수 있습니다. 이를 효과적으로 처리하기 위해 동적 자료 구조를 사용하는 것이 좋습니다. ​

     

    7. 배열 크기 조절에 따른 성능 저하 : 배열의 크기를 빈번하게 조절하는 경우, 성능 저하가 발생할 수 있습니다. 배열 크기 조절은 새 배열 생성, 기존 데이터 복사, 기존 배열 삭제 등의 작업을 포함하므로, 배열 크기를 조절하는 것이 성능에 미치는 영향을 고려해야 합니다. 배열의 길이 및 크기 조절이 빈번한 경우, ArrayList나 LinkedList와 같은 동적 자료 구조를 사용하여 성능과 메모리 관리를 개선하는 것을 고려해보세요. ​

     

    8. 불필요한 배열 크기 조절 방지 : 배열 크기 조절은 리소스 소모가 크므로, 불필요한 배열 크기 조절을 최대한 줄이는 것이 좋습니다. 이를 위해 배열을 사용하기 전에 필요한 최소한의 크기를 예측하고, 배열 크기를 적절하게 설정하세요. ​

     

    이렇게 배열의 기본 구조를 이해하고 사용하면, 자바에서 배열을 효율적으로 활용하여 다양한 프로그래밍 작업을 수행할 수 있습니다. 배열은 데이터 관리의 효율성, 성능 향상, 다양한 알고리즘 구현, 다차원 데이터 구조 등 다양한 목적으로 활용됩니다.

     

     

    댓글