혼자 공부하는 자바 - 13장. 컬렉션 프레임워크

youngtae·2023년 5월 2일
0

자바 이론

목록 보기
12/12
post-thumbnail

자바는 널리 알려져 있는 자료구조를 사용해서 객체들을 효율적으로 추가, 삭제, 검색할 수 있도록
인터페이스와 구현 클래스를 java.util패키지에 제공.
이들을 총칭해서 컬렉션 프레임워크라고 함.
주요 인터페이스로는 List, Set, Map이 있음


컬렉션 프레임워크

List컬렉션

  • List 컬렉션은 배열과 비슷하게 객체를 인덱스로 관리
  • 배열과의 차이점은 저장 용량이 자동으로 증가하며, 객체 저장할 때 자동 인덱스가 부여됨
  • List 컬렉션은 객체 자체를 저장하는 것이 아니라 객체의 번지를 참조하기 때문에 동일 객체 중복 저장할 수 있는데, 이 경우 동일한 번지를 참조
  • null도 저장 가능

List 인터페이스의 메서드

List<String> list = ...; // list에 저장되는 객체를 String 타입으로 하겠다
list.add("홍길동"); // 맨 끝에 객체 추가
list.add(1, "신용권"); // 지정된 인덱스에 객체 삽입
String str = list.get(1); // 인덱스로 객체 검색
list.remove(0); // 인덱스로 객체 삭제
list.remove("신용권"); // 객체 삭제
for (int i=0; i<list.size(); i++){
	String str = list.get(i); // i인덱스에 저장된 String 객체를 가져옴
}

for (String str: list){ 
	// list에 저장된 객체 수만큼 반복하면서 객체를 하나씩 str에 대입
}

ArrayList

  • 저장할 객체 타입을 E 타입 파라미터에 표기하고 기본 생성자를 호출
    List<String> list = new ArrayList<String>();
    List<String> list = new ArrayList<>(); 
    // 타입 생략하면 왼쪽 list에 지정된 타입 따라감
  • 기본 생성자로 객체 생성하면 10개 객체 저장할 수 있는 초기 용량 가짐, 객체 수 늘어나면 자동 증가
  • 0번 인덱스부터 차례대로 저장되며, 특정 인덱스 객체 삭제되면 한 칸씩 앞으로 당겨짐 삽입하면 한 칸씩 뒤로 밀려남
  • 객체 삽입, 삭제가 빈번하게 일어나는 경우에는 적절하지 않음

Vector

  • Vector는 ArrayList와 동일한 내부 구조 가지고 있음
  • 저장할 객체 타입 표기하고 생성자 호출
    List<E> list = new Vector<E>();
    List<E> list = new Vector<>(); 
    // 타입 생략하면 왼쪽 list에 지정된 타입 따라감
  • ArrayList와 다른 점은 동기화된 메서드로 구성되어 있기 때문에 멀티 스레드가 동시에 Vector의 메서드들을 실행할 수 없고, 하나의 스레드가 메서드 실행을 완료해야만 다른 스레드가 메서드를 실행할 수 있음 → 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제 할 수 있음
    import java.util.List;
    import java.util.Vector;
    
    public class VectorExample {
    	public static void main(String[] args) {
    		List<Board> list = new Vector<Board>();
    	
    		list.add(new Board("제목1", "내용1", "글쓴이1"));
    		list.add(new Board("제목2", "내용2", "글쓴이2"));
    		list.add(new Board("제목3", "내용3", "글쓴이3"));
    		list.add(new Board("제목4", "내용4", "글쓴이4"));
    		list.add(new Board("제목5", "내용5", "글쓴이5"));
    		
    		list.remove(2);
    		list.remove(3);
    		
    		for(int i=0; i<list.size(); i++) {
    			Board board = list.get(i);
    			System.out.println(board.subject + "\t" + board.content + "\t" + board.writer);
    		}
    	}
    }
    //출력결과
    제목1	내용1	글쓴이1
    제목2	내용2	글쓴이2
    제목4	내용4	글쓴이4

LinkedList

  • ArrayList와 사용 방법은 같지만 내부 구조는 완전 다름
  • ArrayList는 내부 배열에 객체를 저장해서 관리하지만, LinkedList는 인접 참조를 링크해서 관리

  • 특정 인덱스 객체를 제거하면 앞뒤 링크만 변경되고 나머지 링크는 그대로
  • 빈번한 삽입, 삭제가 일어나는 경우에 좋은 성능
  • 객체 타입 표기하고 생성자 호출
List<E> list = new LinkedList<E>();
List<E> list = new LinkedList<>(); 
// 타입 생략하면 왼쪽 list에 지정된 타입 따라감
  • 끝에서부터 순차적으로 추가 또는 삭제하는 경우는 ArrayList가 빠르지만, 중간에 추가, 삭제 하는 경우는 앞뒤 링크 정보만 변경하면 되는 LinkedList가 더 빠름

Set 컬렉션

  • List 컬렉션은 객체의 저장 순서를 유지하지만, Set컬렉션은 저장 순서가 유지되지 않음
  • 객체를 중복해서 저장할 수 없고, 하나의 null만 저장 가능
  • HashSet, LinkedHashSet, TreeSet 등이 있음

Set 인터페이스의 메서드

  • Set 컬렉션은 인덱스로 객체를 가져오는 메서드가 없음, 대신 전체 객체를 대상으로 한 번씩 반복해서 가져오는 iterator 제공
Set<String> set = ...;
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
	//String 객체 하나를 가져옴
	String str = iterator.next();
}

//삭제
while (iterator.hasNext()){
	String str = iterator.next();
	if(str.equals("홍길동")){
		iterator.remove();
	}
}

HashSet

Set<String> set = new HashSet<E>(String);
Set<E> set = new HashSet<E>();
  • HashSet은 객체들을 순서 없이 저장하고 동일한 객체는 중복 저장하지 않음
  • 동일 객체 판단 기준
    • 객체를 저장하기 전에 먼저 객체의 hashCode() 메서드를 호출해서 해시코드 얻음
    • 이미 저장되어 있는 객체들의 해시코드와 비교
    • 동일한 해시코드 있다면 다시 equals() 메서드로 두 객체를 비교해서 true면 동일 객체 판단

Map 컬렉션

  • Map 컬렉션은 키와 값으로 구성된 Map.Entry 객체를 저장하는 구조
  • Entry는 Map 인터페이스 내부에 선언된 중첩 인터페이스
  • 키는 중복 저장될 수 없지만 값은 중복 저장 가능
  • 기존에 저장된 키와 동일한 키로 값을 저장하면 기존의 값은 없어지고 새로운 값으로 대체
  • HashMap, Hashtable, LinkedHashMap, Properties, TreeMap

Map 인터페이스의 메서드

Map<String, Integer> map = ...;  // 키는 String 타입, 값은 Integer 타입으로
map.put("홍길동", 30); // 객체 추가
int score = map.get("홍길동"); // 객체 찾기
map.remove("홍길동"); // 객체 삭제

HashMap

  • 키와 값의 타입은 기본 타입(byte, int, float, double, char)을 사용할 수 없고 클래스 및 인터페이스 타입만 사용 가능
Map<K, V> map = new HashMap<K, V>();
K = 키 타입
V = 값 타입

Map<String, Integer> map = new HashMap<String, Integer>();
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class HashMapExample {
	public static void main(String[] args) {
		//Map 컬렉션 생성
		Map<String, Integer> map = new HashMap<String, Integer>();
		
		//객체 저장
		map.put("신용권", 85);
		map.put("홍길동", 90);
		map.put("동장군", 80);
		map.put("홍길동", 95);  // 키가 같아서 값 대체
		System.out.println("총 Entry 수: " + map.size());
		
		//객체 찾기		
		System.out.println("\t홍길동 : " + map.get("홍길동"));
		System.out.println();
		
		//객체를 하나씩 처리
		Set<String> keySet = map.keySet();
		Iterator<String> keyIterator = keySet.iterator();
		while(keyIterator.hasNext()) {
		  String key = keyIterator.next();
		  Integer value = map.get(key);
		  System.out.println("\t" + key + " : " + value);
		}		
		System.out.println();	
		
		//객체 삭제
		map.remove("홍길동");
		System.out.println("총 Entry 수: " + map.size());
		
		//객체를 하나씩 처리
		Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
		Iterator<Map.Entry<String, Integer>> entryIterator = entrySet.iterator();
		while(entryIterator.hasNext()) {
		  Map.Entry<String, Integer> entry = entryIterator.next();
		  String key = entry.getKey();
		  Integer value = entry.getValue();
		  System.out.println("\t" + key + " : " + value);
		}
		System.out.println();
		
		//객체 전체 삭제
		map.clear();
		System.out.println("총 Entry 수: " + map.size());
	}
}

//출력결과Entry: 3
	홍길동 : 95

	홍길동 : 95
	신용권 : 85
	동장군 : 80Entry: 2
	신용권 : 85
	동장군 : 80Entry: 0

Hashtable

  • HashMap과 동일한 내부 구조
  • 차이점은 Hashtable은 동기화된 메서드로 구성되어 있기 때문에 멀티 스레드가 동시에 Hashtable의 메서드들을 실행할 수 없고, 하나의 스레드가 실행 완료해야만 다른 스레드 실행 가능
  • 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있기 때문에 스레드에 안전
Map<K, V> map = new Hashtable<K, V>();
K = 키 타입
V = 값 타입

Map<String, Integer> map = new Hashtable<String, Integer>();

LIFO와 FIFO 컬렉션

Stack

LIFO(후입선출) 자료구조를 구현한 클래스

주요 메서드

리턴 타입메서드설명
Epush(E item)주어진 객체를 스택에 넣음
Epeek()스택의 맨 위 객체를 가져옴
Epop()스택의 맨 위 객체를 가져오고 스택에서 제거
//생성
Stack<E> stack = new Stack<E>();

Queue

FIFO(선입선출) 자료구조 구현한 클래스

주요 메서드

리턴 타입메서드설명
booleanoffer(E item)주어진 객체를넣음
Epeek()객체 하나를 가져옴
Epoll()객체를 가져오고 큐에서 제거
  • Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList
Queue<E> queue = new LinkedList<E>();
// LinkedList 객체를 Queue 타입으로 변
profile
나의 개발기록

0개의 댓글