본문 바로가기
Java

[Java] Collection Framework1 - List(ArrayList / Vector / LinkedList)

by 건복치 2020. 4. 21.
반응형
이것이 자바다 - 신용권의 Java 프로그래밍 정복2를 보고 정리한 내용입니다.

변수란?

하나의 값을 저장할 수 있는 메모리 공간

수시로 값이 '변'동될 수 있기 때문에 변수라는 이름을 갖게 되었다.

 

그런데 저장해야할 데이터의 수가 많아진다면?

그만큼 많은 변수를 만들어야 하는 걸까?

그렇게 된다면 굉장히 비효율적일 것

 

Array

그래서 같은 타입의 많은 데이터를 다루는 효율적인 방법이 바로 배열

같은 타입의 데이터를 연속된 공간에 나열시키고, 각 데이터에 인덱스(index), 순서를 부여해 놓은 자료구조

 

그런데 배열은 쉽게 사용할 수 있지만, 저장할 수 있는 데이터(객체)의 수가 배열을 생성할 때 결정되는 구조이다.

그렇기에 크기가 고정되어 있고 사용 중 크기를 변경할 수 없다.

불특정 다수의 객체를 저장하기에는 문제!

배열의 크기를 크게 생성해도 되긴 하지만 객체를 삭제한다면 해당 인덱스가 빌 거고 낭비되는 공간이 발생할 것

그렇다고 일일이 어디가 비어있는지 확인하는 것도 비효율적

 

 

 

 

그래서 자바는 배열의 이러한 문제점을 해결하고 자료구조를 바탕으로 객체들을 효율적으로 저장(추가), 삭제, 검색할 수 있도록

java.util 패키지에 컬렉션과 관련 인터페이스, 클래스들을 포함시켜놓았다.

이들을 Collection Framework라고 부르며 객체를 수집해서 저장하는 역할을 한다.

 

Collection FrameWork

*Collection - 요소를 수집해서 저장하는 것 의미

*Framework - 사용 방법을 미리 정해 놓은 라이브러리 의미

 

컬렉션 프레임워크는 몇 가지 인터페이스를 통해 다양한 컬렉션 클래스를 이용할 수 있도록 한다.

주요 *인터페이스로 List, Set, Map이 있다.

*Interface - 컬렉션을 사용하는 방법을 정의한 것

 

https://minwan1.github.io/2018/07/03/2018-07-03-collection/

 

Hierarchy of Collection Framework (https://cornerstones.tech/java-collections/)

 

Hierarchy of Map (https://cornerstones.tech/java-map/)

 

List와 Set은 객체를 추가, 삭제, 검색하는 방법에 많은 공통점이 있기 때문에 이 인터페이스들의 공통된 메소드들만 모아 Collection 인터페이스로 정의해 두고 있다.

Map은 키와 값을 하나의 상으로 묶어서 관리하는 구조로 되어있어 위와는 사용 방법이 완전히 다르다.

 

 

인터페이스 분류

특징

구현 클래스

Collection

List

-순서를 유지하고 저장

-중복 저장 가능

ArrayList, LinkedList, Vector

Set

-순서를 유지하기 않고 저장

-중복 저장 안 됨

HashSet, TreeSet

Map

-키와 값의 쌍으로 저장

-키는 중복 저장 안 됨

HashMap, Hashtable, TreeMap, Properties

 

 

Collections class(아직 정리 X)

https://minhamina.tistory.com/21

Collections 클래스는 Collection 인터페이스를 상속받은 인스턴스를 반환하는 정적 메소드로 구성된 유틸리티 클래스.

List 컬렉션

객체를 일렬로 늘어놓은 구조로 저장 시 자동으로 객체마다 인덱스가 부여된다.

인덱스로 객체를 검색, 삭제할 수 있다.

객체 자체를 저장하는 것이 아니라 객체의 번지를 참조한다.

동일한 객체를 중복 저장할 수 있고, 이 경우 동일한 번지가 참조된다.

null도 저장할 수 있으며, 이 경우 해당 인덱스는 객체를 참조하지 않는다.

 

 

 

 

List 인터페이스 메소드

기능 메소드 설명
객체 추가 boolean add(E e) 주어진 객체를 맨 끝에 추가
void add(int index, E element) 주어진 인덱스에 객체를 추가
set(int index, E element) 주어진 인덱스에 저장된 객체를 주어진 객체로 바꿈
객체 검색 boolean contains(Object o) 주어진 객체가 저장되어 있는지 여부
E get(int index) 주어진 인덱스에 저장된 객체를 리턴
isEmpty() 컬렉션이 비어 있는지 조사
int size() 저장되어 있는 전체 객체수를 리턴
객체 삭제 void clear() 저장된 모든 객체를 삭제
E remove(int index) 주어진 인덱스에 저장된 객체를 삭제
boolean remove(Object o) 주어진 객체를 삭제

 

*List 인터페이스는 제네릭 타입이기 때문에 리턴 타입은 E / 구체적인 타입은 구현 객체를 생성할 때 결정됨

 

//제네릭을 적용하지 않은 자바4 이전의 코드
//객체가 저장될 때 object타입으로 변환되어 저장되기 때문에 모든 종류의 객체 저장 가능
//그러나 저장할 때 object로 변환하고, 찾아올 때 원래 타입으로 변환해야 하므로 실행 성능에 좋지 못함
//자바 5부터 제네릭을 도입해 저장할 객체 타입을 지정함으로써 불필요한 타입 변환을 하지 않도록 함
List list = new List();

//제네릭스를 반영한 코드
//제네릭스를 이용하면 형변환에 의한 불필요한 코딩, 잘못된 형변환에 의한 런타임 오류등에서 벗어날 수 있게 된다.
List<String> list = new List<String>();

list.add("minha");
list.add(1, "kwon");
String str = list.get(1);
list.remove(0);
rest.remove("kwon");

//저장된 총 객체 수만큼 루핑
for(int i = 0; i < list.size(); i++) {
	String str = list.get(i);
}

for(String str : list) {

}

 

ArrayList

List 인터페이스의 구현 클래스

객체 추가 시 인덱스로 관리

배열과 달리 저장 용량을 초과한 객체들이 들어오면 자동적으로 저장 용량이 늘어난다.

기본 생성자로 ArrayList 객체를 생성하면 내부에 10개의 객체를 저장할 수 있는 초기 용량(capacity)을 가지게 된다.

저장되는 객체 수가 늘어나면 용량이 자동적으로 증가하지만, 처음부터 용량을 크게 잡고 싶다면 용량의 크기를 매개 값으로 받는 생성자를 이용

 

 

ArrayList<E> list = new ArrayList<E>();

ArrayList<String> list = new ArrayList<String>(30);

 

ArrayList에서 특정 인덱스의 객체를 제거하면 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1씩 당겨진다.

마찬가지로 특정 인덱스에 객체를 삽입하면 해당 인덱스부터 마지막 인덱스까지 모두 1씩 밀려난다.

 

 

 

빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList를 사용하는 것이 바람직하지 않다.

이런 경우에는 LinkedList를 사용하는 것이 더 좋다.

그러나 인덱스 검색이나, 맨 마지막에 객체를 추가하는 경우에는 ArrayList가 더 좋은 성능을 발휘한다.

 

*고정된 객체들로 구성된 List를 생성할 경우

List<T> list = Arrays.asList(T... a);

 

ArrayList<String> list = Arrays.asList("minha", "kwon", "hello");
for(String str : list) {
	System.out.println(str);
}

 

Vector

Vector<E> list = new Vector<E>();

ArrayList와 동일한 내부 구조를 가지고 있다.

다른 점은 Vector는 동기화된(synchronized) 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 이 메소드들을 실행할 수 없고, 하나의 스레드가 실행을 완료해야만 다른 스레드를 실행할 수 있다.

그래서 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있다.

스레드가 안전(Thread Safe)하다.

 

 

 

 

LinkedList

ArrayList와 사용 방법은 똑같지만 내부 구조는 정말 다르다.

ArrayList는 내부 배열에 객체를 저장해서 인덱스로 관리하지만, LinkedList는 인접 참조를 링크해서 체인처럼 관리한다.

 

 

 

LinkedList에서 특정 인덱스의 객체를 제거하면 앞뒤 링크만 변경되고 나머지 링크는 변경되지 않는다.

삽입도 마찬가지다.

그렇기 때문에 빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList보다 LinkedList가 좋은 성능을 발휘한다.

 

 

 

LinkedList<E> list = new LinkedList<E>();

 

구분 순차적으로 추가/삭제 중간에 추가/삭제 검색
ArrayList 빠르다 느리다 빠르다
LinkedList 느리다 빠르다 느리다

 

관련 포스트

[Java] Collection Framework2 - Set(HashSet / LinkedHashSet / TreeSet)
[Java] Collection Framework 3 - Map(HashMap / LinkedHashMap / TreeMap / HashTable/ Properties)

 

참고

이것이 자바다 - 신용권의 Java 프로그래밍 정복2
반응형

'Java' 카테고리의 다른 글

[Java] Mac - Eclipse 관련 참고 및 정리  (0) 2020.04.22
[Java] Iterator / ListIterator  (0) 2020.04.22
[Java] Stack, Queue 클래스  (0) 2020.04.21
[Java] BufferedReader, BufferedWriter  (0) 2020.04.07
[Java] 자바 관련 참고 사이트 정리  (0) 2020.03.03

댓글