JavaScript

웹 개발의 필수 언어

동적인 웹 페이지 구현을 위한 핵심 프로그래밍 언어.

Java

객체지향 프로그래밍

안정적이고 확장성 있는 백엔드 개발의 대표 언어.

HTML

웹의 기초

웹 페이지의 구조를 정의하는 마크업 언어.

React

현대적 UI 라이브러리

효율적인 사용자 인터페이스 구축을 위한 JavaScript 라이브러리.

CSS

웹 디자인의 핵심

웹 페이지의 시각적 표현을 담당하는 스타일 언어.

Spring

자바 웹 프레임워크

기업급 애플리케이션 개발을 위한 강력한 프레임워크.

Java/자바 학습

자바의 배열

lamarcK 2025. 5. 9. 13:31
//배열 기본 구조
// 배열 선언
int[] numbers;                 // 선언만 하기
int[] numbers = new int[5];    // 선언과 초기화
int[] numbers = {1, 2, 3, 4, 5}; // 선언과 동시에 값 할당

// 배열 사용
numbers[0] = 10;  // 값 할당
int value = numbers[0];  // 값 접근
int length = numbers.length;  // 배열 길이

2차원 배열:
// 배열 선언
int[][] matrix;                    // 선언만 하기
int[][] matrix = new int[3][4];   // 3행 4열 배열 생성
int[][] matrix = {                 // 선언과 동시에 값 할당
    {1, 2, 3, 4},
    {5, 6, 7, 8},
    {9, 10, 11, 12}
};

// 배열 사용
matrix[0][0] = 1;  // 값 할당
int value = matrix[0][0];  // 값 접근

배열의 개념과 동작 방식

배열은 동일한 타입의 여러 데이터를 연속된 메모리 공간에 저장하는 자료구조다.

선언 시 크기가 고정되며, 인덱스를 통해 각 요소에 빠르게 접근할 수 있다.

JVM은 배열 생성 시 힙 메모리에 연속된 공간을 할당하고, 배열 변수는 이 메모리의 시작 주소를 참조한다.

쉬운 설명과 비유

배열은 마치 번호가 매겨진 사물함과 같다. 각 사물함은 같은 크기이고(동일 타입), 번호순서대로 붙어있으며(연속된 메모리), 한 번 만들면 사물함의 개수를 바꿀 수 없다.(고정 크기).

배열의 주요 역할

  • 데이터의 순차적 저장
  • 인덱스를 통한 빠른 접근
  • 동일 타입 데이터의 그룹화
  • 반복 작업의 효율적 처리

사용 이유와 목적

  • 다수의 변수를 효율적으로 관리
  • 데이터 처리의 일관성 확보
  • 메모리의 효율적 사용
  • 알고리즘 구현의 용이성

자주하는 실수

  • ArrayIndexOutOfBoundsException (인덱스 범위 초과)
  • 배열 크기를 동적으로 변경하려는 시도
  • 배열 초기화 없이 사용
  • 참조형 배열에서 객체 생성 누락

배열형 데이터 목록

⭐ : 사용 빈도

  1. 기본 배열
    • 일반 배열 (Array)⭐
    • 다차원 배열 (Multi-dimensional Array)⭐
  2. List 인터페이스 구현체
    • ArrayList⭐⭐
    • Vector (쓰레드 안전)
    • LinkedList⭐
    • Stack (Vector 상속)
  3.  Queue 인터페이스 구현체
    • PriorityQueue⭐
    • ArrayDeque
    • LinkedList (Queue 구현)
  4.  Set 인터페이스 구현체 (순서 없는 컬렉션)
    • HashSet⭐
    • TreeSet
    • LinkedHashSet
  5.  Map 인터페이스 구현체 (키-값 쌍)
    • HashMap⭐
    • TreeMap⭐
    • LinkedHashMap⭐
    • Hashtable (쓰레드 안전)
  6.  특수 목적 배열
    • Arrays 클래스의 유틸리티
    • Collections 클래스의 유틸리티
    • StringBuffer/StringBuilder (문자 배열)
    • BitSet (비트 배열)
  7.  동기화된(Thread-safe) 컬렉션
    • CopyOnWriteArrayList
    • ConcurrentHashMap⭐
    • Vector
    • Hashtable

실무 활용 예시

// 1. 데이터 일괄 처리
int[] scores = new int[100];
for(int i = 0; i < scores.length; i++) {
    processScore(scores[i]);
}

// 2. 캐시 구현
Object[] cache = new Object[1000];

// 3. 이미지 픽셀 처리
int[][] pixels = new int[width][height];

// 4. 고정 크기 버퍼
byte[] buffer = new byte[8192];

// 5. 테이블 데이터 처리
String[][] tableData = new String[rows][columns];

// 6. 정렬 알고리즘 구현
public void bubbleSort(int[] arr) {
    // 정렬 로직
}

// 7. 통계 데이터 처리
double[] measurements = new double[1000];

이러한 배열은 성능이 중요하거나 크기가 고정된 데이터를 다룰 때 특히 유용합니다. 하지만 크기가 동적으로 변해야 하는 경우에는 ArrayList나 다른 컬렉션을 고려해야 합니다.


Java에서 가변 길이 데이터를 다루는 주요 방법들

ArrayList 사용 (가장 일반적인 방법)

// 기본 사용
ArrayList<Integer> list = new ArrayList<>();
list.add(1);  // 동적으로 추가
list.add(2);
list.add(3);

// 초기 용량 지정
ArrayList<Integer> list = new ArrayList<>(1000); // 성능 최적화

// 배열을 ArrayList로 변환
Integer[] array = {1, 2, 3};
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(array));

LinkedList 사용

LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("첫번째");
linkedList.addFirst("맨앞에 추가");
linkedList.addLast("맨뒤에 추가");

ArrayList와 LinkedList의 주요 차이점

동적 배열 재할당

// 수동으로 배열 크기 조정
public class DynamicArray {
    private int[] array;
    private int size;

    public DynamicArray() {
        array = new int[10]; // 초기 크기
        size = 0;
    }

    public void add(int element) {
        if (size == array.length) {
            // 배열이 가득 차면 크기를 2배로 증가
            int[] newArray = new int[array.length * 2];
            System.arraycopy(array, 0, newArray, 0, array.length);
            array = newArray;
        }
        array[size++] = element;
    }
}
//실제 과정
// 1. 처음 상태 (크기 10)
array = [1][2][3][4][5][6][7][8][9][10]
                                        ↑ 가득 참

// 2. 새로운 배열 생성 (크기 20)
newArray = [][][][][][][][][][][][][][][][][][][]

// 3. 기존 데이터 복사
newArray = [1][2][3][4][5][6][7][8][9][10][][][][][][][][][][]

// 4. array 변수가 새로운 배열을 가리키도록 변경
array = newArray

// 5. 기존 배열은 더 이상 참조되지 않아 가비지 컬렉션의 대상이 됨
[1][2][3][4][5][6][7][8][9][10] // 이 메모리는 결국 해제됨
  1. 새로운 더 큰 배열을 만들고
  2. 기존 데이터를 복사한 후
  3. 기존 배열은 버려지고(가비지 컬렉션됨)
  4. 새로운 배열을 사용하게 된다.

배열 크기 조정의 비효율성


Collection 구현체들의 특징 비교

구현체 장점 단점 사용 시나리오
ArrayList - 빠른 조회
- 순차적 추가/삭제 빠름
- 중간 삽입/삭제 느림 - 데이터 조회가 많은 경우
- 순차적 추가/삭제가 많은 경우
LinkedList - 중간 삽입/삭제 빠름
- 메모리 효율적
- 조회 속도 느림 - 삽입/삭제가 많은 경우
- 메모리가 제한적인 경우
Vector - 스레드 안전 - 성능 저하 - 멀티스레드 환경

실무에서 자주 사용되는 패턴

// 1. 동적 데이터 수집
public List<String> collectData() {
    List<String> data = new ArrayList<>();
    while (hasMoreData()) {
        data.add(getData());
    }
    return data;
}

// 2. 초기 크기 예측이 가능한 경우
public List<User> getUsers(int expectedSize) {
    List<User> users = new ArrayList<>(expectedSize);
    // ... 데이터 추가
    return users;
}

// 3. 배열과 리스트 변환
public class DataProcessor {
    // 리스트를 배열로 변환
    public String[] listToArray(List<String> list) {
        return list.toArray(new String[0]);
    }

    // 배열을 리스트로 변환
    public List<String> arrayToList(String[] array) {
        return new ArrayList<>(Arrays.asList(array));
    }
}

성능 최적화 팁

// 1. 초기 용량 지정으로 재할당 횟수 줄이기
List<Integer> list = new ArrayList<>(10000);

// 2. 정확한 크기를 알 때는 배열 사용
int[] array = new int[exactSize];

// 3. 메모리 최적화
list.trimToSize(); // 사용하지 않는 공간 제거

주의사항

  • ArrayList는 내부적으로 배열을 사용하므로 크기가 커질 때 재할당이 발생
  • 초기 용량을 너무 크게 잡으면 메모리 낭비
  • 멀티스레드 환경에서는 동기화 고려 필요
  • 기본 타입의 경우 박싱/언박싱 오버헤드 발생
  • 이러한 방법들 중에서 대부분의 경우 ArrayList를 사용하는 것이 가장 좋은 선택
  • 특별한 요구사항(예: 많은 삽입/삭제, 스레드 안전성 등)이 있는 경우에만 다른 대안을 고려

자바 vs 자바스크립트 배열 차이점