[Java]자바 컬렉션 프레임워크(Java Collection Framework)

Wintering·2022년 5월 17일
0

이펙티브 자바

목록 보기
4/18

컬렉션 프레임워크

ex. 10개의 Product 객체를 저장해 두고, 필요할 때 마다 하나씩 꺼내서 이용한다고 가정한다.
어떻게 Product를 효율적으로 추가, 검색, 삭제할 수 있을까? 👉 배열을 이용한다.

하지만 배열은 저장할 수 있는 객체 수가 배열을 생성할 때 결정되서 불특정 다수일 경우는 문제가 있다.
또한, 객체를 삭제하는 경우 인덱스가 비게되어 새로운 객체를 저장하려면 어디가 비어있는지 확인하는 코드도 필요하다.

이러한 문제점을 해결하기위해, 널리 알려져있는 자료구조를 바탕으로!
객체들을 효율적으로 추가,삭제, 검색할 수 있도록 java.util 패키지에 컬렉션에 관련 된 인터페이스와 클래스들을 포함시켜놓았는데, 이게 바로 컬렉션 프레임워크(Collection Framework)다.
Collection : 요소를 수집해서 저장
Framework : 사용방법을 미리 정해 놓은 라이브러리

👉일정 타입의 데이터들이 모여 쉽게 가공 할 수 있도록 지원하는 자료구조들의 기본 구조

  • ArrayList, Vector, LinkedList는 List 인터페이스를 구현하는 클래스
    List 인터페이스로 사용이 가능하다.

  • HashSet, TreeSet은 Set interface를 구현하는 클래스
    Set 인터페이스로 사용 가능하다.

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

List

  • 배열과 비슷, 객체를 인덱스로 관리
  • 배열과 다르게, 저장용량이 자동으로 증가하고, 저장할 때 '자동'으로 인덱스를 부여한다.
  • 인덱스로 객체를 검색, 삭제할 수 있는 기능을 제공하고 List 컬렉션은 객체 자체를 저장하는 것이 아니라 객체의 번지를 참조하는 형태로 사용한다.
  • 동일한 객체를 중복 저장할 수 있는데, 이 경우 동일한 번지가 참조되고 null이 저장 될 경우 객체를 참조하지 않는다.
메소드설명
add(E e)객체를 맨끝에 추가
add(int index, E element)주어진 인덱스를 객체에 추가
set(int index, E element)주어진 인덱스의 저장된 객체를 주어진 객체로 변경
contains(Object o)주어진 객체가 저장되어 있는지의 여부 판단
get(int index)저장된 객체 리턴
isEmpty()컬렉션이 비어있는지 조사
size()저장되어 있는 전체 객체 수를 리턴
clear()저장 된 모든 객체 삭제
remove(int index)주어진 인덱스에 저장된 객체 삭제
remove(Object o)주어진 객체 삭제

ArrayList

  • List의 인터페이스 구현 클래스 ArratList에 객체를 추가하면 객체가 인덱스로 관리됨
  • ArrayList는 모든 종류의 객체를 저장할 수 있다. 이유는 객체가 저장될 때 Object 타입으로 변환되어 저장되기 때문이다.
    👉다만, 저장할 때 Object로 변환하고, 찾아올 때 원래 타입으로 변환하므로 실행 성능에 좋지 못한 영향을 미치기도 한다. 이 때문에, <> 제네릭 타입지정이 생겨남.
  • ArrayList에 객체를 추가하면 0부터 차례대로 저장된다.
  • ArrayList에서 특정 인덱스의 객체를 제거하면 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1씩 당겨진다.
    👉빈번한 삭제와 삽입이 일어나는 경우, ArrayList는 바람직하지 못하다. (LinkedList 권장)

Vector

  • ArrayList와 동일한 내부구조를 가졌다.
  • ArrayList와의 차이점은 Vector는 동기화된(synchronized) 메소드로 구성되어 있기 때문에, 멀티 스레드가 동시에 이 메소드를 실행할 수 없고, 하나의 스레드가 실행을 완료해야만 다른 스레드를 실행할 수 있다
    👉멀티 스레드 환경에서 안전하게 객체를 추가, 삭제가 가능 (Thread Safe)

LinkedList

  • ArrayList와 사용방법은 같지만 내부 구조는 완전히 다르다.
  • ArrayList는 내부 배열에 객체를 저장하여 인덱스로 관리하지만, LinkedList는 인접 참조를 링크해서 체인처럼 관리한다.
    👉특정 인덱스의 객체를 제거하면 앞뒤 링크만 변경되고 나머지 링크는 변경되지 않음

Set

HashSet

TreeSet(검색기능강화)

Map

HashMap

Hashtable

Properties

TreeMap(검색기능강화)

LIFO , FIFO 컬렉션

Stack

  • LIFO : Last In First Out / 나중에 넣은 객체가 먼저빠져나가는 자료구조
  • Stack
    ex. JVM 스택 메모리, (스택 메모리에 저장된 변수는 나중에 저장된 것부터 제거된다.)
메소드설명
push(E item)주어진 객체를 스택에 넣는다.
peek()스택 맨 위의 객체를 가져온다. 객체를 스택에서 제거하지 않는다.
pop()스택의 맨 위 객체를 가져온다. 객체를 스택에서 제거한다.
public Class coin(){
	private int value;
    
    public coin(int value){
    this.value = value;
    }
    
    public int getValue(){
    	return value;
    }
}
import java.util.*;

public class StackExample{
	public static void main(Stirng[] args){
    	Stack<Coin> coinBox = new Stack<Coin>()'
        
        coinBox.push(new Coin(100));
        coinBox.push(new Coin(50));
        coinBox.push(new Coin(500));
        coinBox.push(new Coin(10));
        
        while(!coinBox.isEmpty()){
        	Coin coin = coinBox.pop();
            System.out.println("꺼내온 동전 : " + coin.getValue() + "원");
        }
    }
}

결과 : (먼저 넣은 동전이 나중에 나옴)
꺼내온동전 : 10원
꺼내온동전 : 500원
꺼내온동전 : 50원
꺼내온동전 : 100원

Queue

  • FIFO : First In First Out / 먼저 넣은 객체가 먼저 빠져나가는 구조
  • Queue
    ex. 스레드풀(ExecutorService), (작업 큐는 먼저 들어온 작업부터 처리한다.)
메소드설명
offer(E item)주어진 객체를 넣는다.
peek()객체를 가져온다. 객체를 제거하지 않는다.
poll()객체를 가져온다. 객체를 제거한다.
  • Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList.
Queue<E> queue = new LinkedList<E>();
public class Message{
	public static void main(String[] args){
    	public String command;
        public String to;
        
        public Message(String command, String to){
        	this.command = command;
            this.to = to;
        }
    } 
}
import java.util.LinkedList;
import java.util.Queue;

public class QueueExample{
	public static void main(String[] args){
    	Queue<Message> messageQueue = new LinkedList<Message>();
        
        //메세지 저장
        messageQueue.offer(new Message("sendMail", "달구"));
        messageQueue.offer(new Message("sendSMS", "빙고"));
        messageQueue.offer(new Message("sendKaKaoTalk", "부강"));
        
        //메세지 큐가 비었는지 확인
        while(!messageQueue.isEmpty()){
        	//메세지 큐에서 한개의 메시지를 꺼냄
        	Message message = messageQueue.poll();
            switch(message.command){
            	case "sendMail":
                	System.out.println(message.to + "님에게 메일을 보냅니다.");
                	break;
                case "sendSMS":
                	System.out.println(message.to + "님에게 SMS를 보냅니다.");
                    break;
                case "sendKaKaoTalk":
                	System.out.println(message.to + "님에게 카카오톡을 보냅니다.");
                   	break;
                
            }
        }
    }
}

- 결과 (먼저 넣은 메세지가 먼저 나옴)
달구님에게 메일을 보냅니다.
빙고님에게 sms를 보냅내다.
부강님에게 카카오톡을 보냅니다.

0개의 댓글