위로 아래

콜렉션 프레임워크

콜렉션 (collerction) 프레임워크

  1. 배열의 한계를 극복하면서, 일반적인 자료구조(data structure)도 쉽게 이용할 수 있도록 다양한 클래스와 인터페이스를 정의한 프레임워크.
  2. 콜렉션 : 데이터를 한 곳에 모아 편리하게 저장 및 관리하는 가변 크기의 객체 컨테이너.
  3. 콜렉션 프레임워크 : 객체를 한 곳에 모아 효율적으로 관리하고 편리하게 사용할 수 있도록 제공하는 환경.

 

특징

  1. 많은 데이터 요소를 효율적으로 관리하기 위한 자료 구조
  2. 콜렉션은 제네릭(generics) 형식으로 구현되어 있다.
  3. 콜렉션 클래스가 데이터를 다룰 때, 데이터는 기본적으로 객체만 가능 (기본형 사용 불가. 대신 포장 클래스 이용해야 한다)
  4. 콜렉션 인터페이스는 java.util에 포함되어 있다.
  5. 콜렉션 프레임워크는 인터페이스와 구현 클래스들로 구성되어 있다. (밑에 표 외에도 Iterator, Enumeration 인터페이스도 포함된다)

 

 

종류

  1. List : 이름과 같이 목록처럼 데이터 순서에 따라 관리
  2. Set : 중복이 허용되지 않는 데이터를 관리
  3. Map : 데이터를 Key와 Value로 짝을 이루어 관리하며, Key값은 중복을 허용 X
  4. Queue : 데이터를 FIFO 방식으로 관리
  5. Stack : 데이터를 LIFO 방식으로 관리
  6. ArrayList, LinkedList, Vector, Stack, HashSet, TreeSet, HashMap, TreeMap 등
인터페이스 특징 구현 클래스
Collection List 객체의 순서가 있고, 중복될 수 있다. ArrayList, Stack, Vector, LinkedList
Queue 입력한 순서대로 저장되며, 객체가 중복될 수 있다. DelayQueue, PriorityQueue, LinkedList
Set 순서가 없으며, 객체가 중복될 수 없다. HashSet, TreeSet, EnumSet
Map 키-값이 쌍으로 저장되며, 키는 중복될 수 없다. HashMap, Hashtable, TreeMap, Properties

 

 

 


Collections 클래스

  1. Collection을 다루기 위한 클래스
  2. java.util 패키지에 들어 있다.
  3. Collection 인터페이스와는 다른 것.
  4. 콜렉션 원소 정렬, 원소 돌리기, 원소 섞기, 원소 탐색을 쉽게 해결할 수 있다.

 

원소 정렬

  1. 매개변수가 제네릭 타입<>이지만 편의상 생략한다
  2. sort(), reverse(), reverseOrder() 메소드 제공
import java.util.*;

public class SortDemo {
	public static void main(String[] args) {
		String[] fruits = {"포도","수박","사과","키위","망고"};
		List<String> list = Arrays.asList(fruits);
		
		Collections.sort(list,Collections.reverseOrder());
		System.out.println(list);
		
		Collections.reverse(list);
		System.out.println(list);
	}
}

 

 

 

원소 돌리기, 섞기

  1. 원소 돌리기 : 명시된 거리만큼 원소를 돌려 나열
  2. 섞기 : 원소를 무작위로 나열
  3. rotate() 메소드 : 돌리기
  4. shuffle()메소드 : 섞기
import java.util.*;

public class ShuffleDemo {
	public static void main(String[] args) {
		List<Character> list = new ArrayList<>();
		
		for(char c='A' ; c <= 'G' ; c++) {
			list.add(c);
		}
		
		System.out.println("최초 리스트 : \t" + list);
		
		Collections.rotate(list, 3);
		System.out.println("돌린 리스트 : \t" + list);
		
		Collections.shuffle(list);
		System.out.println("섞은 리스트 : \t" + list);
	}
}

 

 

원소 탐색

  1. 조건을 만족하는 원소 찾기
  2. 정렬된 리스트라면, binarySearch() 메소드를 이용해 원하는 원소를 찾을 수 있다
  3. 인덱스 값이 반환된다
import java.util.*;

public class SearchDemo {
	public static void main(String[] args) {
		String[] s = {"황금을","돌","같이","보라"};
		List<String> list = Arrays.asList(s);
		
		Collections.sort(list);   // 탐색 전에는 정렬이 먼저 되어 있어야 한다
		System.out.println(list);
		
		System.out.println(Collections.binarySearch(list, "보라"));   // 인덱스 번호를 반환
	}
}

 

 

Collections 클래스의 여러 메소드들

  1. addAll() : 명시된 원소들을 컬렉션에 삽입
  2. copy() : 리스트를 다른 리스트로 복사
  3. disjoint() : 2개의 컬렉션에서 공통된 원소가 없으면 true, 있으면 false를 반환
  4. fill() : 리스트의 모든 원소를 특정 값으로 덮어쓰기
  5. frequency() : 컬렉션에 주어진 원소의 빈도수 반환
  6. max() : 리스트에서 최대값을 반환
  7. min() : 리스트에서 최솟값을 반환
  8. nCopies() : 매개변수 값으로 주어진 객체를 주어진 횟수만큼 복사해 List 객체를 반환
  9. reverse() : 리스트의 원소들을 역순으로 정렬
  10. swap() : 리스트에서 주어진 위치에 있는 두 원소를 교체

 

frequency 예시

더보기
import java.util.*;

public class EtcDemo {
	public static void main(String[] args) {
		List<String> list1 = List.of("사과","포도","수박","사과","키위","포도","망고","사과");
		
		HashSet<String> set = new HashSet<>(list1);
		
		List<String> list2 = new ArrayList<>(list1);
		Collections.sort(list2);
		
		for(String fruit : list2) {
			System.out.printf("%s : %d\n", fruit, Collections.frequency(list1,fruit));;
		}
	}
}

 

 


반복자 Iterator

  1. 반복자.
  2. Collection 인터페이스에서 iterator() 메소드로 제공.
  3. iterator를 이용하면 콜렉션에 포함된 원소를 순차적으로 순회할 수 있다. (Map 콜렉션은 반복자를 제공하지 않는다)

 

Iterator 인터페이스주요 메소드

  1. hasNext() : 다음 원소의 존재 여부를 반환
  2. next() : 다음 원소를 반환
  3. remove() : 마지막에 순회한 콜렉션의 원소를 삭제

 

모든 원소를 순회하는 Iterator 반복문

Iterator<String> iterator = collection.iterator();
while(iterator.hasNext()){
	String s = iterator.next();
}


for(String s : collection) {

}

 

Iterator 예시

더보기
import java.util.*;

public class IteratorDemo {
	public static void main(String[] args) {
		Collection<String> list = Arrays.asList("다람쥐","개구리","나비");   // 콜렉션이라는 가장 상위 인터페이스 자료형으로 만들었다
		
		Iterator<String> iterator = list.iterator();   // 순서대로 정렬 (인덱스 번호는 없다)
		while (iterator.hasNext())
			System.out.print(iterator.next() + " - ");
		System.out.println();
		// 요소를 사용해서 iterator가 비어 있음
		
		while(iterator.hasNext())
			System.out.print(iterator.next() + " + ");
		System.out.println();
		// iterator가 비어 있으므로 아무 것도 출력되지 않음
		
		iterator = list.iterator();
		// iterator 다시 채워줌
		while (iterator.hasNext())
			System.out.print(iterator.next() + " = ");
	}
}

 

 

 


List 인터페이스

// 생성 방법 1
String[] animal = {"사슴","호랑이","바다표범","곰");
List<String> s1 = Arrays.asList(animal);

// 생성 방법 2
List<Integer> s2 = List.of(10,20,30);
  1. 순서가 있는 객체를 중복 여부와 상관 없이 저장하는 리스트 자료구조를 지원
  2. 배열과 유사하지만 크기가 가변적(동적)
  3. 대표적인 List 콜렉션으로는 ArrayList, LinkedList, Stack, Vector가 있다

 

List 인터페이스 주요 메소드

  1. add(인덱스, 객체) : 인덱스 위치에 객체를 추가
  2. get(인덱스) : 인덱스에 있는 객체를 반환
  3. indexOf(객체) : 명시한 객체가 있는 첫 번째 인덱스 반환
  4. remove(인덱스) : 인덱스에 있는 객체를 제거
  5. set(인덱스, 객체) : 인덱스에 있는 객체와 주어진 객체를 교환
  6. of() : 불변 리스트. 수정할 수 없고 원소로 null을 사용할 수 없다.

 

 

 


List : ArrayList

// ArrayList 생성 방법
ArrayList<String> a1 = new ArrayList<String>(50);   //capacity를 50으로 설정. (기본값 10)

// List를 ArrayList 타입으로 생성
List<String> s1 = new ArrayList<>(list);
  1. List 인터페이스의 구현 클래스
  2. Arrays 클래스의 메소드가 아니다. 별개의 것.
  3. 배열을 기반으로 한 콜렉션의 하나.
  4. 배열 안의 중간 데이터를 추사하거나 삭제할 시, 동적으로 배열의 길이가 조절된다.
  5. 초기 용량은 10, 용량을 초과할 경우 배열의 크기를 1.5배로 증가시킨다
  6. 배열과의 다른 점 : 배열은 길이가 고정되어 있으나, ArrayList는 배열의 길이를 자동으로 조절해주어 가변적이다

 

 

 


List : Linked List

  1. List 인터페이스의 구현 클래스
  2. 이중 연결 리스트
  3. 이웃한 원소를 이중으로 연결한다.
  4. 원소를 추가하거나 할 때 인덱스 조정 없이 전후 원소의 참조 값만 수정하면 되므로 효율적이다
  5. 메모리 부담이 크다
  6. 빠르게 자주 조회해야 하면 ArrayList가 좋고, 읽어오는 방향이 매번 순방향 역방향 바뀌면 LinkedList가 좋다
구분 ArrayList 클래스 LinkedList 클래스
구현 가변 크기 배열 (동적) 이중 연결 리스트
초기 용량 10 0
get() 연산 빠름 느림
add(), remove() 연산 느림 빠름
메모리 부담 적음 많음
Iterator 순방향 순방향, 역방향

 

예시

더보기
import java.util.*;

public class PerfomanceDemo {
	public static void main(String[] args) {
		ArrayList<Integer> al = new ArrayList<>();
		LinkedList<Integer> ll = new LinkedList<>();
		
		long start = System.nanoTime();
		for(int i=0;i<100000;i++)
			al.add(0,i);
		long end = System.nanoTime();
		long duration = end - start;
		System.out.println("ArrayList로 삽입한 시간 : " + duration);
		
		start = System.nanoTime();
		for(int i=0;i<100000;i++)
			ll.addFirst(i);
		end = System.nanoTime();
		duration = end - start;
		System.out.println("LinkedList로 삽입한 시간 : " + duration);
		
		start = System.nanoTime();
		for(int i=0;i<al.size();i++)
			al.get(i);
		end = System.nanoTime();
		duration = end - start;
		System.out.println("ArrayList로 조회한 시간 : " + duration);
		
		start = System.nanoTime();
		for(int i=0;i<100000;i++)
			ll.get(i);
		end = System.nanoTime();
		duration = end - start;
		System.out.println("LinkedList로 조회한 시간 : " + duration);
	}
}

 

 


List : Stack

//문자열 스택 생성
Stack<String> s1 = new Stack<>();
  1. List 인터페이스의 구현 클래스
  2. LIFO(Last In First Out) 방식 (후입선출)
  3. stack은 인덱스 번호가 1부터 시작한다

Stack 주요 메소드

  1. empty() : 스택이 비어 있는지 확인하고 true 또는 false 반환
  2. peek() : 스택의 최상위 원소를 제거하지 않고, 반환만 한다
  3. pop() : 스택의 최상위 원소를 스택에서 제거하고, 반환한다
  4. push(원소) : 스택의 최상위에 원소를 추가한다
  5. search(원소) : 주어진 원소의 인덱스값(1부터 시작)을 반환한다

 

예시

더보기
import java.util.Stack;

public class StackDemo {
	public static void main(String[] args) {
		Stack<String> s1 = new Stack<>();
		
		s1.push("사과");
		s1.push("바나나");
		s1.push("체리");
		System.out.println(s1.peek());
		
		System.out.println(s1.pop());
		System.out.println(s1.pop());
		System.out.println(s1.pop());
		
		Stack<Integer> s2 = new Stack<>();
		
		s2.add(10);
		s2.add(20);
		s2.add(1,100);
		
		for(int x:s2)
			System.out.print(x + " ");
		System.out.println();
		
		while(!s2.empty())
			System.out.print(s2.pop() + " ");
	}
}

 


Queue 인터페이스

  1. FIFO(First In First Out) tjsdlqtjscnf
  2. 후단(tail)에서 원소를 추가하고, 전단(head)에서 원소를 제거
  3. 큐의 중간에서는 원소를 추가하거나 제거할 수 없다
  4. Queue에 포함된 구현 클래스 종류 : ArrayDeque, DelayQueue, LinkedList (LinkedList는 다중 구현)

 

Queue 인터페이스 주요 메소드

  1. offer() : 삽입
  2. poll() : 삭제
  3. peek() : 검색
  4. add(), remove(), element() 메소드도 사용할 수 있지만, 큐 크기를 초과하거나 해당 요소가 없으면 예외를 발생시킨다.

 

예시

더보기
import java.util.*;

public class QueueDemo {
	public static void main(String[]args) {
		Queue<String> q = new LinkedList<>();
		
		//q.remove()   // 요소가 없을 때 remove 쓰면 예외 발생
		System.out.println(q.poll());   // poll은 예외를 발생하지 않고 null을 반환
        
		q.offer("사과");
		System.out.println("바나나를 추가했나요?" + q.offer("바나나"));

		head = q.poll();
		System.out.println(head + "제거하기");
		System.out.println("새로운 헤드 : " + q.peek());
		
		System.out.println("체리를 포함하고 있나요?" + q.contains("체리"));
		System.out.println("사과를 포함하고 있나요?" + q.contains("사과"));
	}
}

 


Set 인터페이스

// 생성
Set<String> s = new HashSet<>();

// 불변 Set (of 사용)
Set<String> s = Set.of("포도","수박","사과","키위","망고");

// HashSet 생성
Set<String> s = Set.of("포도","수박","사과","키위","망고");
HashSet<String> hs = new HashSet<>(s);

// TreeSet 생성
Set<String> s = Set.of("포도","수박","사과","키위","망고");
TreeSet<String> ts = new TreeSet<>(s);
  1. 순서가 없으며, 중복되지 않는 원소를 저장하는 자료구조를 지원한다.
  2. Set에서 같은 객체란, 두 객체의 hashCode() 값이 같고 equals()의 반환 값이 true인 객체이다.
  3. Set에 포함된 구현 클래스 종류
    1. HashSet : 내부적으로 해싱(hashing)을 이용한 Set 구현체. null도 원소로 추가할 수 있다. 해시 테이블을 이용하기 때문에 탐색 속도가 빠르다.
    2. TreeSet : 이진탐색트리 형태를 이용한 Set 구현체. 오름차순으로 원소를 저장. 이진 탐색 트리를 사용하기 때문에 데이터 정렬이 가능.

 

Set 인터페이스 주요 메소드

  1. add(요소) : Set에 요소 추가 (이미 있는 개체는 추가 요청 무시됨. null도 추가 가능)
  2. remove(요소) : Set에 있는 해당 요소 제거
  3. contains(요소) : Set이 해당 요소를 포함하고 있으면 true, 아니면 false 반환
  4. addAll(배열 혹은 리스트) : 배열이나 리스트에 있는 모든 요소를 Set에 추가
  5. clear() : Set의 모든 요소 제거

 

HashSet 예시

더보기
import java.util.*;

public class HashSet1Demo {
	public static void main(String[] args) {
		String[] fruits = {"사과", "바나나", "포도", "수박"};
		Set<String> h1 = new HashSet<>();
		Set<String> h2 = new HashSet<>();
		
		for(String s:fruits)
			h1.add(s);
		
		System.out.println("1단계 : " + h1);
		
		h1.add("바나나");
		h1.remove("포도");
		h1.add(null);
		
		System.out.println("2단계 : " + h1);
		
		System.out.println(h1.size());
		System.out.println(h1.contains("수박"));
		
		List<String> list = Arrays.asList(fruits);
		h2.addAll(list);
		System.out.println("3단계 : " + h2);
		h2.clear();
		System.out.println("h2가 비었는지? " + h2.isEmpty());
	}
}

 

TreeSet 예시

더보기
import java.util.*;

public class TreeSetDemo {
	public static void main(String[] args) {
		Set<String> s = Set.of("포도","수박","사과","키위","망고");
		
		HashSet<String> hs = new HashSet<>(s);   // 무질서
		System.out.println(hs);
		
		TreeSet<String> ts = new TreeSet<>(s);   // String 가나다 순서로 정렬
		System.out.println(ts);
		
		System.out.println(ts.first());
		System.out.println(ts.last());
		System.out.println(ts.lower("사과"));
		System.out.println(ts.higher("사과"));
	}
}

 

 

 

 


Map 인터페이스

// 기본형
Map<String, Integer> fruits = new HashMap<>();

// .of() 사용 불변 map 생성 
Map<String, Integer> fruits = Map.of("사과",5,"바나나",3,"포도",10,"딸기",1);

// Map은 인터페이스라 객체 생성 불가능. 타입으로는 쓸 수 있으니까, HashMap으로 구현하고 Map을 인터페이스로 쓸 수는 있음
  1. 키-값으로 구성된 객체를 저장하는 자료구조.
  2. Map이 사용하는 키와 값도 모두 객체이다.
  3. 순서가 없다. (랜덤으로 나온다)
  4. 키는 중복되지 않고 하나의 값에만 매핑되어 있다. (키가 있다면 대등하는 값을 얻을 수 있다)
  5. 중복을 허용하지 않기 위해 hashCode()와 equals() 메소드를 오버로딩한다
  6. 키와 밸류를 모두 저장하느라 메모리 낭비가 많다는 단점이 있다.
  7. Map에 포함된 구현 클래스 종류
    1. HashMap : 키-값으로 null 사용 가능. 
    2. Hashtable : 키-값으로 null 사용 불가능. 동기화된 메소드로 구현되어 스레드에 안전
    3. 일반적으로 동기화가 필요 없다면 굳이 Hashtable을 이용하지 않아도 된다.

 

Map 인터페이스 주요 메소드

  1. clear() : 모든 키값을 제거
  2. containsKey(키) : 키의 존재 여부를 조사해서 true, false로 반환
  3. containsValue(값) : 값의 존재 여부를 조사해서 true, false로 반환
  4. entrySet() : 모든 키-값을 Set 타입으로 반환
  5. get(키) : 키에 해당하는 값을 반환
  6. isEmpty() : Map이 비어 있는지 여부를 조사해서 true, false로 반환 
  7. keySet() : 모든 키를 Set 타입으로 변환
  8. put(키, 값) : 주어진 키-값을 저장하고 값을 반환
  9. remove(키) : 키에 대응하는 원소를 삭제하고 값을 반환
  10. size() : Map의 크기를 반환
  11. of() : 수정할 수 없는 맵 (자바 9부터)

 

 

Map 메소드 예시

Map<String, String> map = new HashMap<String, String>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");
        map.put("key4", "value4");
        map.put("key5", "value5");

 

 

entrySet(): key, value 모두 출력

for (Map.Entry<String, String> entry : map.entrySet()) {
	System.out.println("[key]:" + entry.getKey() + ", [value]:" + entry.getValue());
}

 

 

keySet() : key 값만 출력

for (String key : map.keySet()) {
	String value = map.get(key);
	System.out.println("[key]:" + key + ", [value]:" + value);
}

 

 

entrSet().Iterator() : entrySet 컬렉션 순회

while (iteratorE.hasNext()) {
	Map.Entry<String, String> entry = (Map.Entry<String, String>) iteratorE.next();
   	String key = entry.getKey();
   	String value = entry.getValue();
   	System.out.println("[key]:" + key + ", [value]:" + value);
}

 

 

keySet().iterator() : keySet 컬렉션 순회

Iterator<String> iteratorK = map.keySet().iterator();
while (iteratorK.hasNext()) {
	String key = iteratorK.next();
	String value = map.get(key);
	System.out.println("[key]:" + key + ", [value]:" + value);
}

 

 

 

 

 

https://tychejin.tistory.com/31

 

[Java] Map 전체 출력(entrySet, keySet, Iterator, Lambda, Stream)

Map 전체 출력 Map에 값을 전체 출력하기 위해서는 entrySet(), keySet() 메소드를 사용하면 되는데 entrySet() 메서드는 key와 value의 값이 모두 필요한 경우 사용하고, keySet() 메서드는 key의 값만 필요한 경

tychejin.tistory.com

 

 

Map 예시

더보기
import java.util.*;

public class MapDemo {
	public static void main(String[] args) {
		Map<String, Integer> fruits = Map.of("사과",5,"바나나",3,"포도",10,"딸기",1);
		System.out.println(fruits.size() + "종류의 과일이 있다.");
		System.out.println(fruits);
		
		for(String key : fruits.keySet()) {
			System.out.println(key + "의 개수 : " + fruits.get(key));
		}
		
		String key = "바나나";
		if(fruits.containsKey("바나나")) 
			System.out.println(key + "가 " + fruits.get(key) + "개 있다.");
		
		fruits.forEach((k,n) -> System.out.print(k+"("+ n + ")"));
	}
}

 

HashMap 예시

더보기
import java.util.*;

public class HashMap1Demo {
	public static void main(String[]args) {
		Map<String, Integer> map = Map.of("사과",5,"바나나",3,"포도",10,"딸기",1);
		
		Map<String, Integer> fruits = new HashMap<>(map);
		fruits.put("귤", 2);
		System.out.println("지금 과일 종류 개수 : " + fruits.size());
		fruits.remove("바나나");
		System.out.println("나중 과일 종류 개수 : " + fruits.size());
		
		fruits.put("망고", 2);
		System.out.println("현재 과일 종류 : " + fruits);
		
		fruits.clear();
		System.out.println("clear 후 과일 종류 : " + fruits);
		
	}
}