본문 바로가기
넓고 얕은 자료구조 & 알고리즘/자료구조론

자바로 공부하는 배열과 리스트

by 황원용 2023. 10. 30.
728x90

📌 배열(Array)

  • 동일한 데이터 타입의 요소들을 순차적으로 저장하는 자료구조이다.
  • 배열은 고정된 크기를 가지고 있다.
  • 인덱스를 사용하여 요소에 접근할 수 있다.
  • 자바에서는 배열을 선언할 때 크기를 지정하거나, 동적으로 크기를 조정할 수 없다.
    • 요소를 추가하거나 삭제하기 위해서는 새로운 배열을 생성하고 기존의 요소를 복사해야 한다.
  • 배열은 메모리 상에 연속적으로 할당되므로 인덱스를 통한 접근이 매우 빠르다.
    • 또한 크기가 고정되어 있기 때문에 요소의 위치를 바로 계산하여 접근할 수 있다.

 

⌨️ 자바에서의 Array

public static void main(String[] args) {

    String[] strArr = new String[5]; // 초기 배열 크기 5로 설정, 설정하지 않으면 에러 발생
    String[] strArr2 = {"a", "b", "c", "d", "e"}; // 요소 초기화

    System.out.println(strArr); // 출력해보기

    for (String s : strArr) {
        System.out.println(s);
    } // 반복문을 이용하여 하나씩 출력하기

	// 각 인덱스에 요소 넣기
    strArr[0] = "apple";
    strArr[1] = "banana";
    strArr[2] = "cola";
    strArr[3] = "chicken";
    strArr[4] = "pizza";

	//toString 메서드 이용하여 한 번에 출력하기
    System.out.println(Arrays.toString(strArr));
}
  • 문자열 타입의 배열 strArr을 생성하고 배열의 크기를 5로 초기화했다.
  • 혹은, strArr처럼 초기화 시에 중괄호를 사용하여 요소 값을 넣을 수도 있다. 
  • 생성 시에 크기를 지정하지 않으면 에러가 발생한다. 

 

📜 결괏값

  • System.out.println()으로 출력하면 배열 내 요소가 나오는 것이 아니라 메모리의 주소값이 나온다.
  • 따라서 위 예시와 같이 반복문을 통해 예시를 하나씩 출력하는 방법이 있다.
  • 초기 요소는 null이다.
  • 각 인덱스에 값을 넣고 Arrays.toString() 메서드를 사용하면 한 번에 출력도 가능하다.

 

 

🤔 자바에서 배열 복사하기

  • 자바에서 배열은 초기화 시에 요소를 담을 수 있는 배열의 크기가 정해지고 이는 고정되어 바꿀 수 없다.
  • 따라서, 배열에 더 많은 요소를 담기 위해서는 새로 큰 크기의 배열을 만들어 기존 배열의 내용을 복사하여 사용해야 한다.
  • 자바에서는 보통 Arrays.copyOf() 메서드를 사용한다.

 

예시

public static void main(String[] args) {

    String[] strArr1 = new String[5];

    strArr1[0] = "apple";
    strArr1[1] = "banana";
    strArr1[2] = "cola";
    strArr1[3] = "chicken";
    strArr1[4] = "pizza";
    
    String[] strArr2 = {"a", "b", "c", "d", "e"};
    
    // System.arraycopy
    String[] forCopyArr1 = new String[10];
    forCopyArr1[0] = "melon";
    forCopyArr1[1] = "tomato";
    forCopyArr1[2] = "hamburger";

    System.arraycopy(strArr1, 0, forCopyArr1, 3, 4);

    System.out.println("### forCopyArr1 (arraycopy) : " + Arrays.toString(forCopyArr1));

    // Arrays.copyOf

    String[] forCopyArr2;
    forCopyArr2 = Arrays.copyOf(strArr1, strArr1.length);
    System.out.println("### forCopyArr2 (copyOf) : " + Arrays.toString(forCopyArr2));

    // Arrays.copyOfRange
	
    forCopyArr2 = Arrays.copyOfRange(strArr2, 1, 4);
    System.out.println("### forCopyArr2 (copyOfRange) : " + Arrays.toString(forCopyArr2));
}

💡 System.arraycopy의 인자값

  • 첫 번째 인자 : 복사할 배열
  • 두 번째 인자 : 복사할 배열의 복사 시작 인덱스 위치
  • 세 번째 인자 : 복사할 배열을 붙여 넣을 새로운 배열
  • 네 번째 인자 : 새로운 배열에 붙여 넣을 인덱스 위치
  • 다섯 번째 인자 : 복사할 배열의 복사 시작 인덱스로부터 복사할 길이
  • 위의 예시 결괏값은 [melon, tomato, hamburger, apple, banana, cola, chicken, null, null, null]이다.
  • 처음 forCopyArr1의 배열 크기 10을 지정했고, melon, tomato, hamberger 요소를 넣어줬다.
  • 이후에 strArr1의 0번째부터 4 길이의 인덱스를 복사하므로 apple, banana, cola, chicken이 차례로 들어가고 남은 3 개의 요소는 초기값인 null이 된다.

 

💡 Arrays.copyOf의 인자값

  • 첫 번째 인자 : 복사할 배열
  • 두 번째 인자 : 복사 길이

 

💡 Arrays.copyOfRange의 인자값

  • 첫 번째 인자 : 복사할 배열
  • 두 번째 인자 : 복사 시작 인덱스 위치
  • 세 번째 인자 : 복사할 마지막 인덱스 위치 

 

 

🤔 배열 정렬하기

Arrays.sort(arr); // 오름차순
Arrays.sort(arr, Collections.reverseOrder()); // 내림차순
  • Arrays.sort() 메서드를 사용한다.

 

🤔 배열 비교하기

  • Arrays.equals() 메서드를 사용한다.

 

 

📌 리스트 (List)

  • 리스트는 동일한 데이터 타입의 요소들을 순차적으로 저장하는 자료구조이다.
  • 자바에서는 java.util.List 인터페이스를 구현하는 클래스들 (예: ArrayList, LinkedList)을 사용하여 리스트를 생성할 수 있다.
  • 리스트는 크기가 가변적이다.
  • 자바에서의 리스트는 요소의 삽입, 삭제, 검색 등의 기능을 제공한다.

 

💡 ArrayList와 LinkedList의 차이

ArrayList

  • ArrayList는 자바에서 제공하는 동적 배열(dynamic array)로 java.util 패키지에 속해 있다.
    • 위의 일반적인 배열과는 다르게 초기화 시 크기를 고정하지 않기 때문에 동적 배열이라고 부른다.
    • 이는 내부적으로 배열을 사용하여 요소들을 저장하고, 요소를 추가하거나 삭제할 때 배열의 크기를 자동으로 조절하여 유연함을 제공한다.
  • ArrayList는 인덱스 기반(random access) 접근이 가능하다.
    • 각 요소들은 0부터 시작하는 인덱스를 가지고 있으며, 해당 인덱스로 직접 접근하여 값을 가져오거나 변경할 수 있다.
    • 또한 ArrayList는 순차적인 데이터 접근도 효율적이다.
      • 이는 내부적으로 연속된 메모리 공간에 요소들을 저장하기 때문에, 메모리 캐시(cache) 활용 등이 가능하여 성능상 이점을 가진다.

 

LinkedList

  • LinkedList도 java.util 패키지에 속하는 자료구조이며, 연결 리스트(linked list) 형태로 구현되어 있다.
    • LinkedList는 각각의 요소들이 서로 링크(참조)를 통해 연결되어 있는 구조이다.
  • LinkedList에서 각각의 요소(노드)는 값과 다음 노드를 가리키는 포인터(참조)로 구성된다.
    • 따라서 데이터 삽입 및 삭제 시 포인터만 변경하면 되므로 상대적으로 빠른 속도로 처리할 수 있다.
    • LinkedList에서 중간 위치에서 데이터를 삽입하거나 삭제하는 경우, 해당 위치까지 찾아가서 링크만 변경하면 되므로 O(1) 시간복잡도를 가진다.
  • LinkedList의 단점은 인덱스 기반 접근이 비효율적이라는 것이다.
    • 원하는 위치까지 찾아가기 위해서 처음부터 순차 탐색을 거쳐야 하므로 O(n) 시간복잡도가 발생한다.
    • 따라서 임의 위치 조회보다 순차 탐색에 유리한 성능을 보여준다.

 

🤔 ArrayList와 LinkedList 중 어떤 것을 선택해야 하는가?

  • ArrayList : 순차 접근 및 임의 위치 조회가 주요한 경우
  • LinkedList : 중간 삽입/삭제 작업이 많은 경우

 

 

 

참고

뤼튼

https://inpa.tistory.com/entry/JAVA-☕-자바-배열Array-문법-응용-총정리#배열_복사

728x90