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

초보 자바 프로그래밍(34) - 배열과 ArrayList 비교

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

배열과 ArrayList 비교 대표 이미지
배열과 ArrayList 비교 대표 이미지

🔖 INDEX

     

     

    이 글에서는 자바에서 사용하는 배열과 ArrayList의 차이점을 비교하고, 배열 대신 ArrayList를 사용하는 방법에 대해서 알아봅니다. 각각의 특징과 장단점을 이해하고, 언제 어떤 것을 사용하는 것이 좋을지 결정하는 데 도움이 됩니다. 또한, ArrayList의 개념과 사용법을 이해하고, 실제 프로젝트에서 어떻게 활용할 수 있는지 알아봅시다.

     

    배열과 ArrayList 차이점

    배열과 ArrayList는 다음과 같은 차이점이 있습니다:

     

    1. 배열과 ArrayList 개요
      • 배열은 고정된 크기의 연속된 메모리 공간에 동일한 타입의 데이터를 저장하는 기본 자료구조입니다. ArrayList는 java.util 패키지의 클래스로, 동적으로 크기가 조절되는 배열입니다.
      • ArrayList는 내부적으로 배열을 사용하여 데이터를 저장하고 관리합니다. ​
    2. 크기의 유연성 배열
      • 배열의 크기는 선언 시 정해지며, 이후 변경할 수 없습니다. 배열의 크기를 변경하려면 새 배열을 생성하고 기존 데이터를 복사해야 합니다.
      • ArrayList는 동적으로 크기가 조절됩니다. 요소가 추가되거나 제거될 때 자동으로 크기를 조절하며, 필요한 경우 사용자가 명시적으로 크기를 변경할 수도 있습니다. ​
    3. 타입 안전성 배열
      • 배열은 원시 타입(primitive type)과 참조 타입(reference type) 모두 저장할 수 있습니다.
      • ArrayList는 참조 타입만 저장할 수 있습니다. 원시 타입을 저장하려면 해당 타입의 wrapper 클래스를 사용해야 합니다 (예: int -> Integer). ​
    4. 성능 차이 배열
      • 배열은 메모리 상에 연속된 공간에 데이터를 저장하므로, 인덱스를 통한 접근 속도가 빠릅니다. 추가 및 삭제 연산은 직접 구현해야 하며, 크기 변경에 따른 오버헤드가 발생할 수 있습니다.
      • ArrayList는 내부적으로 배열을 사용하므로, 인덱스를 통한 접근 속도는 배열과 거의 동일합니다. 하지만 요소의 추가 및 삭제 시 크기 조절에 따른 오버헤드가 발생할 수 있습니다. ​
    5. 기능 차이 배열
      • 배열은 기본적인 기능만 제공합니다(인덱스로 접근, 크기 조회 등).
      • ArrayList는 다양한 메서드를 제공하여 사용이 편리합니다(요소 추가/삭제, 크기 변경, 정렬, 검색 등) ​
    6. 사용 사례 비교 배열
      • 배열은 크기가 고정되어 있고, 원시 타입을 저장할 수 있을 때 효율적입니다. 예를 들어, 행렬 연산이나 이미지 처리와 같은 상황에서는 배열이 적합합니다.
      • ArrayList는 요소의 추가 및 삭제가 빈번한 경우에 유용하며, 다양한 메서드를 제공하여 사용이 편리합니다. 예를 들어, 사용자의 입력을 동적으로 처리하거나 데이터베이스에서 검색된 레코드를 저장하는 경우에 ArrayList가 적합합니다. ​

    배열과 ArrayList는 각각의 장단점이 있으므로, 상황에 따라 적절한 자료구조를 선택해야 합니다. 배열은 고정된 크기의 데이터를 저장할 때 성능이 우수하며 원시 타입을 저장할 수 있습니다. 반면에 ArrayList는 동적으로 크기가 조절되며 다양한 메서드를 제공하여 사용이 편리하지만, 참조 타입만 저장할 수 있습니다. 프로젝트의 요구 사항을 고려하여 적절한 자료구조를 선택하면 효율적인 코드를 작성할 수 있습니다.

     

     

    배열 대신 ArrayList 사용하는 방법

    ArrayList는 자바에서 제공하는 가변 크기의 배열이며, java.util 패키지에 포함된 클래스입니다. 일반 배열과 달리 크기가 자동으로 조절되어, 요소의 추가 및 삭제가 빈번한 경우에 효율적으로 사용할 수 있습니다. ArrayList는 내부적으로 배열을 사용하여 데이터를 저장하고 관리하며, 제네릭을 지원해 다양한 데이터 타입을 저장할 수 있습니다.

     

    ArrayList의 동작 원리

    ArrayList는 내부적으로 데이터를 저장하기 위해 배열을 사용합니다. 초기에는 일정 크기의 배열이 생성되며, 요소가 추가될 때 배열이 가득 차면 배열의 크기를 자동으로 늘립니다. 일반적으로 배열의 크기는 기존 크기의 1.5배로 증가합니다. 요소가 제거되면 배열의 크기를 줄일 수 있지만, 이 작업은 선택적이며 필요한 경우에만 수행합니다.

     

    ArrayList의 생성 및 초기화

    ArrayList를 사용하려면 먼저 인스턴스를 생성해야 합니다. 다음과 같이 ArrayList의 인스턴스를 생성하고 초기화할 수 있습니다.

    import java.util.ArrayList; // ArrayList를 사용하기 위한 import 구문
    
    ArrayList<Type> arrayList = new ArrayList<>();

    여기서 Type은 ArrayList에 저장할 데이터의 타입을 의미합니다. 예를 들어, 정수를 저장하는 ArrayList를 생성하려면 Type에 Integer를 사용합니다.

     

    자주 사용되는 ArrayList 메서드들

    • add(E e): 요소를 ArrayList의 맨 끝에 추가합니다.
    • add(int index, E e): 지정된 인덱스에 요소를 추가하고, 이후 요소들을 오른쪽으로 이동합니다.
    • get(int index): ArrayList의 지정된 인덱스에 있는 요소를 반환합니다.
    • set(int index, E e): 지정된 인덱스에 있는 요소를 새 값으로 설정합니다.
    • size(): ArrayList에 저장된 요소의 개수를 반환합니다.
    • remove(int index): 지정된 인덱스의 요소를 제거하고, 이후 요소들을 왼쪽으로 이동합니다.
    • clear(): ArrayList의 모든 요소를 제거합니다.
    • indexOf(Object o): 지정된 객체가 ArrayList에 있는 경우, 해당 객체의 인덱스를 반환합니다. 없는 경우 -1을 반환합니다.
    • contains(Object o): ArrayList에 지정된 객체가 포함되어 있는지 여부를 반환합니다.
    • isEmpty(): ArrayList가 비어 있는지 여부를 반환합니다.

     

    다음은 정수를 저장하는 ArrayList를 위의 메서드들을 사용해서 구현한 예제입니다.

    import java.util.ArrayList;
    
    public class ArrayListExample {
    
        public static void main(String[] args) {
            // Integer 타입의 ArrayList 인스턴스를 생성합니다.
            ArrayList<Integer> numbers = new ArrayList<>();
    
            // 요소 추가
            // add() 메서드를 사용하여 numbers 리스트에 숫자를 추가합니다.
            numbers.add(1);
            numbers.add(2);
            numbers.add(3);
    
            // 요소 가져오기 및 출력
            // for문을 사용하여 numbers 리스트의 요소를 반복적으로 접근하고 출력합니다.
            for (int i = 0; i < numbers.size(); i++) {
                System.out.println("Element at index " + i + ": " + numbers.get(i));
            }
    
            // 요소 제거
            // remove() 메서드를 사용하여 인덱스 1에 위치한 요소를 제거합니다.
            numbers.remove(1);  // 인덱스 1의 요소를 제거합니다.
          
            // 제거 후 리스트 출력
            // 인덱스 1의 요소가 제거된 후, numbers 리스트의 요소를 다시 반복적으로 접근하고 출력합니다.
            System.out.println("\nAfter removing element at index 1:");
            for (int i = 0; i < numbers.size(); i++) {
                System.out.println("Element at index " + i + ": " + numbers.get(i));
            }
        }
    }

    위 코드는 Integer 타입의 ArrayList를 생성하고, 요소를 추가, 조회, 제거하는 기본적인 작업을 수행하는 예제입니다. 코드는 다음 단계로 이루어져 있습니다:

    1. Integer 타입의 ArrayList 인스턴스를 생성합니다.
    2. add() 메서드를 사용하여 숫자를 리스트에 추가합니다.
    3. for 문을 사용하여 리스트의 요소를 반복적으로 접근하고 출력합니다.
    4. remove() 메서드를 사용하여 인덱스 1에 위치한 요소를 제거합니다.
    5. 인덱스 1의 요소가 제거된 후, 리스트의 요소를 다시 반복적으로 접근하고 출력합니다. ​

    이 예제는 ArrayList의 기본적인 사용법을 보여주고 있으며, 제네릭을 사용하여 타입 안정성을 확보하고 있습니다.

     

    ArrayList의 장단점

    ArrayList의 주요 장점은 다음과 같습니다.

    • 동적 크기: ArrayList의 크기는 자동으로 조절되어 요소의 추가 및 삭제가 빈번한 경우에 효율적으로 사용할 수 있습니다.
    • 제네릭 지원: ArrayList는 제네릭을 지원하여 다양한 데이터 타입을 저장할 수 있습니다.
    • 인덱스를 통한 빠른 접근: 내부적으로 배열을 사용하므로 인덱스를 통해 요소에 빠르게 접근할 수 있습니다.
    • 다양한 메서드 제공: ArrayList는 다양한 메서드를 제공하여 사용이 편리합니다. ​

     

    ArrayList의 주요 단점은 다음과 같습니다.

    • 원시 타입 저장 불가: ArrayList는 참조 타입만 저장할 수 있으며, 원시 타입을 저장하려면 해당 타입의 wrapper 클래스를 사용해야 합니다(예: int -> Integer).
    • 메모리 오버헤드: ArrayList는 내부적으로 배열을 사용하므로, 크기를 조절하는 과정에서 메모리 오버헤드가 발생할 수 있습니다.
    • 요소 추가 및 삭제 시 성능 저하: ArrayList는 요소의 추가 및 삭제 시 배열의 크기를 조절하거나 요소를 이동해야 하므로, 연산이 빈번한 경우 성능이 저하될 수 있습니다. 이러한 경우 LinkedList와 같은 다른 자료구조를 사용하는 것이 더 효율적일 수 있습니다. ​

     

    ArrayList는 동적 크기와 제네릭 지원, 다양한 메서드 제공 등의 장점을 가지고 있지만, 원시 타입 저장 불가와 메모리 오버헤드, 요소 추가 및 삭제 시 성능 저하 등의 단점도 있습니다. 프로젝트의 요구 사항을 고려하여 적절한 자료구조를 선택하면 효율적인 코드를 작성할 수 있습니다. ​

     

     

    배열 대신 ArrayList 사용 예제

    다음은 배열을 사용한 복잡한 구현 코드 예제와 ArrayList를 사용하여 간단해진 구현 코드 예제입니다.

    public class ArrayExample {
    
        public static void main(String[] args) {
            // 크기가 3인 문자열 배열을 생성합니다.
            String[] words = new String[3];
            words[0] = "hello";
            words[1] = "world";
            words[2] = "java";
    
            // 크기가 4인 새로운 문자열 배열을 생성합니다.
            String[] newWords = new String[4];
            // 새 배열에 이전 배열의 요소를 복사합니다.
            for (int i = 0; i < words.length; i++) {
                newWords[i] = words[i];
            }
            // 새 배열의 마지막 위치에 "programming" 문자열을 추가합니다.
            newWords[3] = "programming";
    
            // 참조를 변경하여 이전 배열을 새 배열로 대체합니다.
            words = newWords;
    
            // for-each문을 사용하여 배열의 모든 요소를 출력합니다.
            for (String word : words) {
                System.out.println(word);
            }
        }
    }

    위 코드는 배열을 사용하여 문자열을 저장하고, 배열의 크기를 동적으로 조정하는 예제입니다. 이 코드는 다음 단계로 이루어져 있습니다: ​

    1. 크기가 3인 문자열 배열을 생성합니다.
    2. 각 요소에 문자열을 저장합니다.
    3. 크기가 4인 새로운 문자열 배열을 생성합니다.
    4. 이전 배열의 모든 요소를 새 배열에 복사합니다.
    5. 새 배열의 마지막 요소에 "programming" 문자열을 추가합니다.
    6. 참조를 변경하여 이전 배열을 새 배열로 대체합니다.
    7. for-each 문을 사용하여 배열의 모든 요소를 출력합니다. ​

    위 코드는 배열을 사용하여 동적 크기 조정을 수행하는 것이 가능하지만, 코드가 상당히 복잡하고 유지보수가 어려울 수 있습니다. 이러한 이유로, ArrayList와 같은 자바의 컬렉션 프레임워크를 사용하여 동적 크기 조정을 수행하는 것이 더 효율적입니다.

     

    다음은 ArrayList를 사용하여 간단해진 구현 코드 예제입니다.

    import java.util.ArrayList;
    
    public class ArrayListExample {
    
        public static void main(String[] args) {
            // ArrayList 인스턴스를 생성합니다.
            ArrayList<String> words = new ArrayList<>();
            // add() 메서드를 사용하여 각 문자열을 추가합니다.
            words.add("hello");
            words.add("world");
            words.add("java");
            words.add("programming");
    
            // for-each문을 사용하여 리스트의 모든 요소를 출력합니다.
            for (String word : words) {
                System.out.println(word);
            }
        }
    }

     

    위 코드는 ArrayList를 사용하여 문자열을 저장하고, add() 메서드를 사용하여 동적으로 크기를 조정하는 예제입니다. 코드는 다음 단계로 이루어져 있습니다: ​

    1. ArrayList 인스턴스를 생성합니다.
    2. add() 메서드를 사용하여 각 문자열을 추가합니다.
    3. for-each 문을 사용하여 리스트의 모든 요소를 출력합니다. ​

    ArrayList를 사용하면 배열과 달리 동적 크기 조정이 가능하며, 코드가 간결하고 가독성이 좋으며, ArrayList의 동적 크기 조정 기능을 활용하므로 배열보다 더 효율적입니다. 또한 제네릭을 사용하여 타입 안정성을 확보하므로, 잘못된 타입의 객체가 리스트에 추가되는 것을 방지할 수 있습니다.

     

     

    댓글