[Java] Array와 List 비교

SeongWon Oh·2021년 9월 1일
1

Java

목록 보기
39/39
post-thumbnail

Array

  • 여러 데이터를 하나의 object로 관리하기 위한 자료구조이다.
  • 논리적 저장 순서와 물리적 저장 순서가 같으며 시작은 0부터 시작한다,
  • Index를 통해 데이터에 접근할 수 있다. (Index가 데이터의 식별자 역할을 한다.)
  • 연속된 메모리 공간에 저장된다.
  • 배열은 정의와 동시에 길이를 지정해야하며 길이를 중간에 바꿀 수 없다.

장점 & 단점

장점

  • 인덱스를 통한 검색이 용이하다
  • 데이터가 연속된 메모리 공간에 저장되어 메모리 관리가 편하다.

단점

  • 고정된 크기의 배열이기에 특정 엘리먼트가 삭제되면 그 공간을 빈 공간으로 남겨두어야하는 메모리 낭비가 발생한다.
  • 정적이므로 배열의 크기를 중간에 변경 못하고 초기에 지정해줘야한다.

배열 선언 및 초기화

  • 배열 선언하기
    • int, char, double, Integer, String등의 자료형으로 선언 가능하다.
    • 배열을 선언하면 int형은 0, double형은 0.0으로 초기화된다.
    • 아래의 두가지 방법으로 []의 위치를 둘 수 있다.
    • 기본 자료형(int, char, double등)의 배열은 선언과 동시에 배열 크기만큼의 메모리가 할당되지만, 객체 배열은 객체의 주소가 들어갈 4/8byte의 메모리 공간만 할당되고 각 객체는 따로 생성하여 저장해야한다. (객체 배열의 초기값은 null)
int[] arr1 = new int[10];
int arr2[] = new int[10];
  • 배열 초기화하기
// 방법1
int[] numbers = new int[] {10, 20, 30};  //개수 생략해야 함

// 방법2
int[] numbers = {10, 20, 30};            // new int[]  생략 가능 

// 방법3
int[] ids; 
ids = new int[] {10, 20, 30};            // 선언후 배열을 생성하는 경우는 new int[] 생략할 수 없음

배열 정렬하기

  • 배열의 정렬을 하기 위해서는 Java.util.Arrays 클래스의 sort() 메서드를 사용하면 간편하게 배열을 정렬할 수 있다.
    • Arrays.sort(배열이름);
  • 기본 오름차순 정렬의 경우는 sort method로 모든 타입에 대해 할 수 있으나 내림차순과 같이 reverse해야하는 경우는 Primitive type(int, char등)으로 만들어진 배열의 경우는 Wrapper class(Integer, String등)로 만들어줘야한다.
    • Arrays.sort(배열이름, Collections.reverseOrder());
  • 배열의 일부분만 정렬하기 위해서는 parameter로 배열의 이름, 배열, 시작index, 끝 index를 대입해줘야한다.
    • Arrays.sort(배열이름, 시작 index, 끝 index);
  • 객체 배열의 정렬은 compareTo함수를 override해줘야한다.
// 기본 정렬
int[] arr = {3,8,43,2,9,15,61,54,3,94,2,10};
Arrays.sort(arr);
     
String[] arr = {"apple","orange","banana","pear","peach","melon"};
Arrays.sort(arr);


// Reverse를 할 경우 Primitive type이 아닌 Wrapper class로 만들어진 배열이어야한다.
Integer[] coinList = {500, 600, 50, 1};
Arrays.sort(coinList, Collections.reverseOrder());


// 배열의 일부분만 정렬
int[] arr = {3,8,43,2,9,15,61,54,3,94,2,10};
Arrays.sort(arr, 2, 5); // 2, 3, 4 요소만 정렬된다.

List

  • 리스트는 배열과 같이 순서가 있는 엘리먼트의 모임이다.
  • ArrayList, LinkedList, Vector가 존재한다.
  • 배열과 다르게 빈 엘리먼트 공간을 허용하지 않는다. (데이터를 빈틈없이 적재한다.) (Java에서는 허용하는 경우도 있다.)
  • Array에서 Index는 데이터의 식별자 역할을 하였지만 List에서는 데이터 삭제시 뒤의 데이터의 위치가 변하게 되어서 List에서의 Index는 데이터의 식별자가 아닌 몇 번째에 위치하였는지에 대한 의미만 갖는다.
  • 데이터의 순차성을 보장하지 못하여서 spacial locality 보장이 되지 않으며 그러한 이유때문에 cash hit이 어렵다.
  • 불연속적으로 메모리 공간을 차지하며 포인터를 통해 접근한다.

장점 & 단점

장점

  • 포인터를 통해 다음 데이터의 위치를 가르키고 있어 데이터의 삽입/삭제가 쉽다.
  • Array와 다르게 동적이므로 배열의 크기가 정해져있지 않다.
  • 물연속적이므로 메모리 관리가 편리하다.

단점

  • 포인터에 대한 추가적인 메모리 공간이 필요하다.(overhead)
  • 검색 성능이 Array와 비교하였을 때 좋지 않다.

Array와 List비교

  • Array는 데이터의 추가/삭제가 느리며 데이터 조회가 빠르다.
  • List는 데이터의 추가/삭제가 빠르며 데이터의 조회가 느리다.
  • 데이터의 추가공간이 필요없이 크기가 정해져있고 추가적인 삽입/삭제 없이 검색을 필요로 할 때 유리하다.
  • 데이터의 크기가 정해져있지 않고 데이터의 삽입/삭제가 많은 경우 유리하다.


Java의 List Collection

ArrayList

  • Array와 같이 ArrayList도 index로 객체를 관리한다.
  • 크기를 동적으로 늘릴 수 있다. (저장 용량을 넘으면 배열 크기가 1.5배가 된다.)
  • ArrayList는 Array와 다르게 특정 index의 객체를 제거하면 뒤에 위치한 객체들이 앞으로 한칸씩 이동한다. (빈 공간을 두지 않는다.)
  • 원소의 이동/추가/삭제 등이 많은 작업을 한다면 ArrayList보다 LinkedList를 사용하는게 효과적이다. 반면에 검색이 많은 경우는 ArrayList를 사용한다.
  • Array는 primitive type과 object를 모두 담을 수 있으나 arrayList는 object element만 담을 수 있다.

ArrayList 선언 및 초기화

ArrayList<Integer> integers1 = new ArrayList<Integer>(); // 타입 지정
ArrayList<Integer> integers2 = new ArrayList<>(); // 타입 생략 가능
ArrayList<Integer> integers3 = new ArrayList<>(10); // 초기 용량(Capacity) 설정
ArrayList<Integer> integers4 = new ArrayList<>(integers1); // 다른 Collection값으로 초기화
ArrayList<Integer> integers5 = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5)); // Arrays.asList()

주요 Method

List<Integer> list = new ArrayList<>();

list에 있는 데이터 개수 찾기
// size()
list.size();

data추가
// add(추가할 데이터)
// 위치 지정을 하고 싶다면 add(추가할 위치, 추가할 데이터);
list.add(10);
list.add(12);

데이터 수정 
// set(데이터 index, 변경할 값);
list.set(0, 15);

Element삭제
// remove(index값 또는 삭제할 값);
// remove method는 해당 index값을 삭제하고 값을 return한다.
list.remove(0);

// 값을 전체 다 삭제할 때는 clear(); 를 호출한다.
list.clear();


값 존재 유무 확인
// contains(찾고자 하는 값);
// contains는 값이 존재하는지에 대한 유무만을 return
list.contains(13);

// indexOf(찾고자 하는 값);
// indexOf는 찾고자 하는 값의 위치를 return해준다. (값이 없으면 -1 return)
list.indexOf(10);


배열이 비었는지 확인
// isEmpty();
// boolean type으로 return된다. 비어있으면 true, 비어있지 않으면 false
list.isEmpty();

LinkedList

  • ArrayList는 하나의 큰 배열을 사용하여 구현하였다면, LinkedList는 각각의 node를 연결하는 방식을 사용한다.
  • LinkedList는 양뱡향 연결 리스트(Doubly Linked List)로 구현되어있다.
  • 인덱스를 갖고 있지 않기 때문에 탐색을 할때는 순차접근만 가능하여 탐색 시간이 오래 걸린다.
  • LinkedList는 ArrayList와는 달리 List 인터페이스를 구현한 AbstractList를 상속하지 않고 AbstractSequentialList를 상속한다.
  • 데이터의 추가/삭제/변경이 많은 경우 좋은 성능을 낸다.

LinkedList 선언 및 초기화

LinkedList<Integer> coffeeMenu = new LinkedList<Integer>(); // 타입 지정, 일반적인 방법
LinkedList<Integer> integers2 = new LinkedList<>(); // 타입 생략 가능
LinkedList<Integer> integers3 = new LinkedList<>(coffeeMenu); // 다른 Collection값으로 초기화
LinkedList<Integer> integers4 = new LinkedList<>(Arrays.asList(1, 2, 3, 4, 5)); // Arrays.asList()

주요 method는 ArrayList와 동일


Vector

  • ArrayList와 동일한 구조를 갖고 있다.
  • Vector 객체를 생성하려면 저장할 타입을 지정해야한다.
  • ArrayList와 다르게 동기화된 메서드로 구성되어 있어 Multi-thread환경에서 안전하게 객체를 추가/삭제 할 수 있다. (Thread safe)
  • ArrayList보다 객체를 추가/삭제하는 속도는 느리다. (낮은 성능)
  • 동기화가 필요 없으면 ArrayList를 사용하는 것이 좋다.
  • 공간 부족시 배열 크기를 2배로 증가한다.

LinkedList 선언 및 초기화

Vector<Integer> vector1 = new Vector<Integer>(); // 타입 지정
Vector<Integer> vector2 = new Vector<>(); // 타입 생략 가능
Vector<Integer> vector3 = new Vector<>(10); // 초기 용량(Capacity) 설정
Vector<Integer> vector4 = new Vector<>(10, 10); // 초기 용량, 증가량 설정
Vector<Integer> vector5 = new Vector<>(vector1); // 다른 Collection값으로 초기화
Vector<Integer> vector6 = new Vector<>(Arrays.asList(1, 2, 3, 4, 5)); // Arrays.asList()

주요 method는 ArrayList와 동일




Reference

profile
블로그 이전했습니다. -> https://seongwon.dev/

0개의 댓글