- 컬렉션(collection) : 여러 객체(데이터)를 담을 수 있는 자료구조, 다수의 데이터 그룹
- 프레임워크(framework) : 표준화, 정형화된 체계적인 프로그래밍 방식
▶ 컬렉션 프레임워크(collection framework) : 배열의 단점을 보완해주는 컬렉션
- 다수의 객체를 다루기위한 표준화된 프로그래밍 방식
- 컬렉션을 쉽고 편리하게 다룰 수 있는 다양한 인터페이스와 클래스 제공
- java.util 패키지에 포함되어있고 JDK1.2부터 제공됨
- 이미 구현되어 있는 것을 사용함으로써 코딩 시간 감소, 코드 품질 보장, 유지보수 용이
▶ 컬렉션 프레임워크의 구성 요소
- 컬렉션 인터페이스 : java.util 패키지 안에 있음
- 컬렉션 클래스 : 컬렉션 인터페이스를 상속받고 java.util 또는 java.util.concurrent 패키지 안에 있음
- 컬렉션 알고리즘 : 검색, 정렬, 셔플과 같은 기능을 제공
컬렉션 인터페이스(Collection Interface)
제네릭(Generics)으로 표현되어 컴파일 시점에서 객체의 타입을 체크하기때문에 에러를 줄이는데 도움이 된다.
예를 들어 런타임시 발생하는 ClassCastException을 컴파일 시점에서 찾아낼 수 있으며,
클래스 캐스팅을 하지않아도 되고 instanceOf를 사용하지 않아도 되서 코드를 좀 더 깔끔하게 유지할 수 있다.
컬렉션 프레임워크의 핵심 인터페이스(List / Set / Map)
List, Set 인터페이스는 Collection 인터페이스를 상속받기 때문에 두 인터페이스의 공통적인 부분을 Collection 인터페이스에서 정의하고 있다.
반면 Map 인터페이스는 구조상의 차이(Key-Value)로 인해 Collection 인터페이스를 상속받지않고 별도로 정의된다.
인터페이스를 크게 3가지로 분류 할 수 있다 -> Collection 인터페이스 그룹 / Map 인터페이스 그룹 / 기타 인터페이스 그룹
1. Collection 인터페이스 그룹
Collection 인터페이스는 직접적인 구현은 제공하지 않으며 모든 컬렉션 클래스가 구현해야하는 메소드를 포함하고있다.
-
boolean add(Object o) : 지정된 객체(o)를 Collection에 추가
-
boolean addAll(Collection c) : Collection의 객체들을 Collection에 추가
-
void clear() : Collection의 모든 객체 삭제
-
boolean contains(Object o) : 지정된 객체(o)가 Collection에 포함되어있는지 확인
-
boolean containsAll(Collection c) : Collection의 객체들이 Collection에 포함되어있는지 확인
-
boolean equals(Object o) : 동일한 Collection인지 비교
-
int hashCode() : Collection의 hash code를 반환
-
boolean isEmpty() : Collection이 비어있는지 확인
-
Iterator iterator() : Collection의 iterator를 얻어서 반환
-
boolean reamove(Object o) : 지정된 객체 삭제
-
boolean removeAll(Collection c) : 지정된 Collection에 포함된 객체들을 삭제
-
boolean retainAll(Collection c) : 지정된 Collection에 포함된 객체만 남기고 다른 객체들은 Collection에서 삭제, 이 작업 후에 Collection에 변화가 있으면 true를 그렇지 않으면 false를 반환
-
int size() : Collection에 저장된 객체의 개수 반환
-
Object[] toArray() : Collection에 저장된 객체를 객체배열로 반환
-
Object[] toArray(Object[] a) : 지정된 배열에 Collection의 객체를 저장해서 반환
2) List Interface -> 순서O 중복O
List 인터페이스는 순서가 있는 컬렉션이며 중복 요소를 포함할 수 있으며 인덱스로 모든 요소에 접근할 수 있다.
ArrayList class, LinkedList class는 List 인터페이스로 구현되었다.
-
void add(int index, Object element) : 지정된 위치(index)에 객체(element)를 추가
-
boolean addAll(int index, Collection c) : 지정된 위치(index)에 컬렉션에 포함된 객체들을 추가
-
Object get(int index) : 지정된 위치(index)에 있는 객체를 반환
-
int indexOf(Object o) : 지정된 객체의 위치(index)를 반환 (List의 첫 번째 요소부터 순방향으로 찾음)
-
int lastIndexOf(Object o) : 지정된 객체의 위치(index)를 반환 (List의 마지막 요소부터 역방향으로 찾음)
-
ListIterator listIterator(), ListIterator listIterator(int index) : List의 객체에 접근할 수 있는 ListIterator를 반환
-
Object remove(int index) : 지정된 위치(index)에 있는 객체를 삭제하고 삭제된 객체를 반환
-
Object set(int index, Object element) : 지정된 위치(index)에 객체(element)를 저장
-
void sort(Comparator c) : 지정된 비교자(comparator)로 List 정렬
-
List subList(int fromIndex, int tolndex) : 지정된 범위(fromIndex부터 tolndex)에 있는 객체 반환
3) Set Interface -> 순서X 중복X
Set 인터페이스는 중복 요소를 포함할 수 없으며 랜덤 액세스를 허용하지않아 iterator 또는 foreach를 이용하여 요소를 탐색할 수 있다.
HashSet class, TreeSet class, LinkedHashSet class는 Set 인터페이스로 구현되었다.
-
Set 인터페이스의 메소드는 Collection 인터페이스의 메소드와 동일하다.
-
boolean add(Object o) : 지정된 객체(o)를 Collection에 추가
-
boolean addAll(Collection c) : Collection의 객체들을 Collection에 추가 (합집합)
-
void clear() : Collection의 모든 객체 삭제
-
boolean contains(Object o) : 지정된 객체(o)가 Collection에 포함되어있는지 확인
-
boolean containsAll(Collection c) : Collection의 객체들이 Collection에 포함되어있는지 확인 (부분집합)
-
boolean equals(Object o) : 동일한 Collection인지 비교
-
int hashCode() : Collection의 hash code를 반환
-
boolean isEmpty() : Collection이 비어있는지 확인
-
Iterator iterator() : Collection의 iterator를 얻어서 반환
-
boolean reamove(Object o) : 지정된 객체 삭제
-
boolean removeAll(Collection c) : 지정된 Collection에 포함된 객체들을 삭제 (차집합)
-
boolean retainAll(Collection c) : 지정된 Collection에 포함된 객체만 남기고 다른 객체들은 Collection에서 삭제, 이 작업 후에 Collection에 변화가 있으면 true를 그렇지 않으면 false를 반환 (교집합)
-
int size() : Collection에 저장된 객체의 개수 반환
-
Object[] toArray() : Collection에 저장된 객체를 객체배열로 반환
-
Object[] toArray(Object[] a) : 지정된 배열에 Collection의 객체를 저장해서 반환
SortedSet 인터페이스는 요소를 오름차순으로 유지하는 Set이다. TreeSet class는 SortedSet 인터페이스로 구현되었다.
Queue 인터페이스는 처리하기 전에 요소를 보유하는 데에 사용된다. 기본 컬렉션 작업 외에도 삽입, 추출 및 검사 작업을 제공한다.
일반적으로 Queue는 요소를 FIFO(First In - First Out)방식으로 정렬하며 예외에는 우선순위 큐가 있다.
PriorityQueue class는 Queue인터페이스로 구현되었다.
Deque 인터페이스는 양쪽 끝에 요소 삽입 및 제거를 지원한다. "double ended queue"의 약자이며 데크라고 읽는다.
ArrayDeque class는 Deque인터페이스로 구현되었다.
2. Map 인터페이스 그룹
1) Map Interface -> 순서X, 중복(키X, 값O)
Map 인터페이스는 키와 값을 매핑힌다. 중복 키가 존재할 수 없으며 각 키는 하나의 값만 매핑할 수 있다.
Map의 기본 연산은 put, get, containsKey, containsValue, size, isEmpty 등이 있다.
HashMap class, TreeMap class, LinkedHashMap class는 Map인터페이스로 구현되었다.
-
void clear() : Map의 모든 객체 삭제
-
boolean containsKey(Object key) : 지정된 key객체와 일치하는 Map의 key 객체가 있는지 확인
-
boolean containsValue(Object value) : 지정된 value객체와 일치하는 Map의 value객체가 있는지 확인
-
Set entrySet() : Map에 저장되어있는 key-value쌍을 Map.Entry타입의 객체로 저장한 Set으로 반환
-
boolean equals(Object o) : 동일한 Map인지 비교
-
Object get(Object key) : 지정한 key객체에 대응하는 value객체를 찾아서 반환
-
int hashCode() : 해시코드를 반환
-
boolean isEmpty() : Map이 비어있는지 확인
-
Set keySet() : Map에 저장된 모든 key객체를 반환
-
Object put(Object key, Object value) : Map에 value객체를 key객체에 연결(mapping)하여 저장
-
void putAll(Map t) : 지정된 Map의 모든 key-value쌍을 추가
-
Object remove(Object key) : 지정한 key객체와 일치하는 key-value객체를 삭제
-
int size() : Map에 저장된 key-value쌍의 개수를 반환
-
Collection values() : Map에 저장된 모든 value객체를 반환
SortedMap 인터페이스는 오름차순의 키 순서로 매핑하는 인터페이스이다.
TreeMap class는 SortedMap인터페이스로 구현되었다.
3. 기타 인터페이스 그룹
Iterator 인터페이스는 어떤 컬렉션이든 반복적으로 수행하기 위한 메소드를 제공한다.
컬렉션 프레임워크에서는 Enumeration 대신 Iterator를 사용하며, 컬렉션 클래스의 Iterator는 Iterator 디자인패턴을 구현한다.
Iterator 메소드를 통해 컬렉션으로부터 Iterator Instance를 가져올 수 있고 컬렉션을 순회하는 도중에 엘리먼트를 삭제할 수 있다.
ListIterator 인터페이스는 어느 방향이든 목록을 탐색하고 반복하면서 목록을 정하고, 목록에서 반복자의 현재 위치를 가져올 수 있다.
ListIterator에는 현재의 요소가 없고, 커서의 위치는 항상 previous()에 대한 호출에 의해 반환될 요소와
next()에 대한 호출에 의해 반환될 요소 사이에 위치한다.
3) Concurrent Interface
-
BlockingQueue 인터페이스
-
TransferQueue 인터페이스
-
BlockingDeque 인터페이스
-
ConcurrentMap 인터페이스
-
ConcurrentNavigableMap 인터페이스
컬렉션 클래스(Collections Class) - 컬렉션 인터페이스에 대한 구현 클래스 제공
일반적으로 쓰이는 클래스
ArrayList, LinkedList, HashSet, TreeSet, PriorityQueue, ArrayDeque, HashMap, TreeMap, LinkedHashMap
Concurrent 클래스
CopyOnWriteArrayList, ConcurrentHashMap, CopyOnWriteArraySet
Legacy 클래스
Vector, Stack, Dictionary, Hashtable, Properties
Abstract 클래스
AbstractList, AbstractSequenctailList, AbstractSet, AbstractQueue
1. List 인터페이스를 구현하는 클래스 -> 순서O, 중복O
- resizable-array이면서 내부적으로 배열을 이용해 순차적으로 요소를 저장하며 비동기이다. (배열기반)
- 동기화가 필요할때는 Collections.synchronizeList() 메소드를 통해 동기화가 보장되는 List를 반환받아 사용한다.
- ArrayList 클래스와 유사한 Vector 클래스는 resizable-array이고 동기화를 보장한다.
- 장점 : 배열은 구조가 간단하고 데이터를 읽는데 걸리는 시간(access time)이 짧다.
- 단점 : 크기를 변경할 수 없다. 크기를 변경해야하는 경우에는 새로운 배열 생성 후 데이터를 복사해야 하며 큰 배열 생성시 메모리가 낭비된다.
package com.collection.java;
import java.util.*;
public class ExArrayList {
public static void main(String[] args) {
ArrayList<Integer> arrList = new ArrayList<Integer>();
// add() 메소드를 이용한 요소의 저장
arrList.add(10);
arrList.add(50);
arrList.add(30);
arrList.add(20);
// for문과 get() 메소드를 이용한 요소의 출력(=객체 반환
for(int i=0;i<arrList.size();i++) {
System.out.print(arrList.get(i)+" ");
}System.out.println();
// remove() 메소드를 이용한 요소의 제거
arrList.remove(1);
// Enhanced for문과 get() 메소드를 이용한 요소의 출력
for(int e:arrList) {
System.out.print(e+" ");
}
System.out.println();
// Collections.sort() 메소드를 이용한 요소의 정렬
Collections.sort(arrList);
// iterator() 메소드와 get() 메소드를 이용한 요소의 출력
Iterator<Integer> iter = arrList.iterator();
while(iter.hasNext()) {
System.out.print(iter.next()+" ");
}System.out.println();
// set() 메소드를 이용한 요소의 변경
arrList.set(0, 100);
for(int e:arrList) {
System.out.print(e+" ");
}System.out.println();
// size() 메소드를 이용한 요소의 총 개수
System.out.println("리스트의 크기 : "+arrList.size());
}
}
/* 출력결과
10 50 30 20
10 30 20
10 20 30
100 20 30
리스트의 크기 : 3
*/
- ArrayList의 배열을 통한 요소 저장의 단점을 극복한 클래스로 내부적으로 연결리스트를 이용하여 요소를 저장한다.
- 연결리스트는 저장된 요소가 비순차적으로 분포되며, 이러한 요소를 링크(link)로 연결하여 구성한다.
- ArrayList의 주요 메소드와 Queue, Deque 속성과 메소드를 가지고 있고 비동기이다.
- 동기화가 필요할때는 Collections.synchronizeList() 메소드를 통해 동기화가 보장되는 List를 반환받아 사용한다.
- 데이터의 삭제 : 단 한번의 참조 변경만으로 가능
- 데이터의 추가 : 한번의 Node객체생성과 두 번의 참조 변경만으로 가능
단일 연결 리스트(singly linked list)
장점 : 요소의 저장과 삭제 작업이 다음 요소를 가리키는 참조만 변경하면 되므로 빠르게 처리 가능
단점 : 현재 요소에서 이전 요소로 접근하기가 어려움
이중 연결 리스트(doubly linked list)
이전 요소를 가리키는 참조도 가지는 이중 연결 리스트가 단일 연결 리스트보다 많이 사용됨
이중 원형 연결 리스트(doubly circular linked list)
package com.collection.java;
//import java.util.LinkedList;
import java.util.*;
public class ExLinkedList {
public static void main(String[] args) {
LinkedList<String> linkList = new LinkedList<String>();
// add() 메소드를 이용한 요소의 저장
linkList.add("넷");
linkList.add("둘");
linkList.add("셋");
linkList.add("하나");
// for문과 get()메소드를 이용한 요소의 출력
for(int i=0; i<linkList.size();i++) {
System.out.print(linkList.get(i)+" ");
}System.out.println();
// remove() 메소드를 이용한 요소의 제거
linkList.remove(1);
// Enhanced for문과 get() 메소드를 이용한 요소의 출력
for(String e : linkList) {
System.out.print(e+" ");
}System.out.println();
// set() 메소드를 이용한 요소의 변경
linkList.set(2, "둘");
for(String e:linkList) {
System.out.print(e+" ");
}System.out.println();
// size() 메소드를 이용한 요소의 총 개수
System.out.println("리스트의 크기 : "+linkList.size());
}
}
/* 출력결과
넷 둘 셋 하나
넷 셋 하나
넷 셋 둘
리스트의 크기 : 3
*/
▶ ArrayList <-> LinkedList 성능 비교
- 순차적으로 데이터를 추가, 삭제할때 : ArrayList가 빠름
- 비순차적으로 데이터를 추가, 삭제할때 : LinkedList가 빠름
- 접근시간(access time) : ArrayList가 빠름
- ArrayList 클래스와 같은 동작을 수행하는 클래스
- ArrayList와 마찬가지로 List 인터페이스를 상속, ArrayList 클래스에서 사용할 수 있는 메소드와 거의 같음
- 현재에는 기존 코드와의 호환성을 위해서만 남아있으므로, 벡터 클래스보다는 ArrayList클래스 사용 권장
2. Set 인터페이스를 구현하는 클래스 -> 순서X, 중복X
- Set 컬렉션 클래스에서 가장 많이 사용되는 클래스 중 하나로 해시 알고리즘(HashMap에서 설명)을 사용하여 검색 속도가 매우 빠름
- HashSet 클래스는 내부적으로 HashMap 인스턴스를 이용하여 요소를 저장함
- Set 인터페이스를 구현하므로, 요소를 순서에 상관없이 저장하고 중복된 값은 저장하지않음
- 객체를 저장하기전에 기존에 같은 객체가 있는지 확인 후 같은 객체가 있으면 저장하지않고 없으면 저장함
- 만약 요소의 저장 순서를 유지해야한다면 LinkedHashSet클래스를 이용할 것
- boolean add(Object o) 메소드는 저장할 객체의 equals()와 hashCode()를 호출(=오버라이딩 되어있어야함)
package com.collection.java;
import java.util.HashSet;
import java.util.Iterator;
public class ExHashSet {
public static void main(String[] args) {
HashSet<String> hs01 = new HashSet<String>();
HashSet<String> hs02 = new HashSet<String>();
// add() 메소드를 이용한 요소의 저장
hs01.add("홍길동");
hs02.add("이순신");
// 중복된 요소 저장 테스트
System.out.println(hs01.add("임꺽정"));
System.out.println(hs01.add("임꺽정"));
// Enhanced for문과 get() 메소드를 이용한 요소의 출력
for(String e:hs01) {
System.out.print(e+" ");
}System.out.println();
// add() 메소드를 이용한 요소의 저장
hs02.add("임꺽정");
hs02.add("홍길동");
hs02.add("이순신");
// Iterator() 메소드를 이용한 요소의 출력
Iterator<String> iter02 = hs02.iterator();
while(iter02.hasNext()) {
System.out.print(iter02.next()+" ");
}System.out.println();
// size() 메소드를 이용한 요소의 총 개수
System.out.println("집합의 크기 : "+hs02.size());
}
}
/* 출력결과
true
false
홍길동 임꺽정
홍길동 이순신 임꺽정
집합의 크기 : 3
*/
package com.collection.java;
import java.util.*;
//사용자가 정의한 클래스의 인스턴스를 HashSet에 저장하기위해
// hashCode()와 equals() 메소드를 오버라이딩한 예제
class Animal{
String species;
String habitat;
Animal(String species, String habitat) {
this.species = species;
this.habitat = habitat;
}
public int hashCode() {
return (species + habitat).hashCode();
}
public boolean equals(Object obj) {
if (obj instanceof Animal) {
Animal temp = (Animal)obj;
return species.equals(temp.species) && habitat.equals(temp.habitat);
} else {
return false;
}
}
}
public class ExHashSet2 {
public static void main(String[] args) {
HashSet<Animal> hs = new HashSet<Animal>();
hs.add(new Animal("고양이", "육지"));
hs.add(new Animal("고양이", "육지"));
hs.add(new Animal("고양이", "육지"));
System.out.println(hs.size());
}
}
/*
출력결과 : 1
*/
2) TreeSet <E> Class - 범위 검색과 정렬에 유리
- TreeSet 클래스는 데이터가 정렬된 상태로 저장되어 범위 검색과 정렬에 유리한 이진 검색 트리(binary search tree)로 구현
- LinkedList처럼 각 요소(node)가 나무(tree)형태로 연결된 구조
- 이진 트리는 모든 노드가 최대 두개의 하위 노드를 갖음(부모-자식관계)
- 이진 검색 트리는 부모보다 작은 값을 왼쪽에, 큰 값은 오른쪽에 저장
- Set 인터페이스를 구현하므로, 요소를 순서에 상관없이 저장하고 중복된 값은 저장하지않음
- HashSet보다 데이터 추가, 삭제에 시간이 더걸림 (반복적인 비교 후 저장하기때문에)
- TreeMap이 근본이 되는 NavigableSet 구현 클래스
-
TreeSet() : 기본 생성자
-
TreeSet(Collection c) : 주어진 컬렉션을 저장하는 TreeSet을 생성
-
TreeSet(Comparator comp) : 주어진 정렬기준으로 정렬하는 TreeSet을 생성
-
Object first() : 정렬된 순서에서 첫 번째 객체 반환
-
Object last() : 정렬된 순서에서 마지막 객체 반환
-
Object ceiling(Object o) : 지정된 객체와 같은 객체를 반환, 없으면 가장 가깝고 큰 값을 가진 객체를 반환, 없으면 null
-
Object floor(Object o) : 지정된 객체와 같은 객체를 반환, 없으면 가장 가깝고 작은 값을 가진 객체를 반환, 없으면 null
-
Object higher(Object o) : 지정된 객체보다 큰 값을 가진 객체 중 제일 가까운 값의 객체를 반환, 없으면 null
-
Object lower(Object o) : 지정된 객체보다 작은 값을 가진 객체 중 제일 가까운 값의 객체를 반환, 없으면 null
-
SortedSet subSet(Object fromElement, Object toElement) : 범위 검색(두 파라미터 사이)의 결과를 반환
-
SortedSet headSet(Object toElement) : 지정된 객체보다 작은 값의 객체들을 반환
-
SortedSet tailSet(Object fromElement) : 지정된 객체보다 큰 값의 객체들을 반환
package com.collection.java;
import java.util.*;
public class ExTreeSet {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<Integer>();
// add() 메소드를 이용한 요소의 저장
ts.add(30);
ts.add(40);
ts.add(20);
ts.add(10);
// Enhanced for문과 get() 메소드를 이용한 요소의 출력
for(int e:ts) {
System.out.print(e+" ");
}System.out.println();
// remove() 메소드를 이용한 요소의 제거
ts.remove(40);
// iterator() 메소드를 이용한 요소의 출력
Iterator<Integer> iter = ts.iterator();
while(iter.hasNext()) {
System.out.print(iter.next()+" ");
}System.out.println();
// size() 메소드를 이용한 요소의 총 개수
System.out.println("이진 검색 트리의 크기 : "+ts.size());
// subSet() 메소드를 이용한 부분 집합의 출력
System.out.println(ts.subSet(10, 20));
System.out.println(ts.subSet(10, true, 20, true));
}
}
/* 출력결과
10 20 30 40
10 20 30
이진 검색 트리의 크기 : 3
[10]
[10, 20]
*/
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)
// 첫 번째와 세 번째 매개변수로 전달된 값에 해당하는 요소를 포함할 것인지? boolean return
3. Map 인터페이스를 구현하는 클래스 -> (key, value)
- Map 인터페이스는 Collection 인터페이스와는 다른 저장 방식(key - value)을 가진다.
- 순서X , key는 중복허용X, value는 중복허용
- Map 인터페이스를 구현한 대표적인 컬렉션 클래스이고, 비동기이며 null을 허용한다는 점을 제외하면 Hashtable과 유사함
- 데이터를 키와 값의 쌍으로 저장하며 해시 알고리즘(hash algorithm)을 사용하여 검색 속도가 빠름
- 순서를 유지하려면 LinkedHashMap클래스를 사용하면 됨
▶ 해시테이블에 저장된 데이터를 가져오는 과정 (환자정보 캐비넷 저장과 비교)
1) key로 해시함수를 호출해서 해시코드를 얻는다.
2) 해시코드(해시함수의 반환값)에 대응하는 linkedlist를 배열에서 찾는다.
3) 키와 일치하는 데이터를 찾는다.
// 해시함수는 같은 키에 대해 항상 같은 해시코드를 반환해야함
-
HashMap() : HashMap 객체 생성
-
HashMap(int initialCapacity) : 지정된 값을 초기용량으로하는 HashMap 객체를 생성
-
HashMap(int initialCapacity, float loadFactor) : 지정된 초기용량과 load factor의 HashMap 객체를 생성
-
HashMap(Map m) : 지정된 Map의 모든 요소를 포함하는 HashMap을 생성
-
Object put(Object key, Object value) : 지정된 키와 값을 HashMap에 저장
-
void putAll(Map m) : Map에 저장된 모든 요소를 HashMap에 저장
-
Object remove(Object key) : HashMap에서 지정된 키로 저장된 값(객체) 제거
-
Object replace(Object key, Object value) : 지정된 키의 값을 지정된 객체(value)로 대체
-
boolean replace(Object key, Object oldVal, Object newVal) : 지정된 키와 객체(oldVal)가 모두 일치하는 경우에만 새로운 객체로 대체
-
boolean containsKey(Object key) : HashMap에 지정된 키가 포함되어있는지 확인
-
boolean containsValue(Object value) : HashMap에 지정된 값이 포함되어있는지 확인
-
Object get(Object key) : 지정된 키의 값을 반환, 못찾으면 null반환
-
Object getOrDefalt(Object key, Object defaultValue) : 지정된 키의 값을 반환, 못찾으면 defaultValue 반환
-
Set entrySet() : HashMap에 저장된 키와 값을 엔트리(키와 값의 결합)의 형태로 Set에 저장해서 반환
-
Set keySet() : HashMap에서 모든 키가 저장된 Set을 반환
-
Collectiion values() : HashMap에 저장된 모든 값을 컬렉션의 형태로 반환
-
void clear() : 저장된 모든 객체를 제거
-
boolean inEmpty() : 해당 HashMap이 비어있는지 확인
-
int size() : HashMap에 저장된 요소의 개수 반환
package com.collection.java;
import java.util.HashMap;
import java.util.Iterator;
public class ExHashMap {
public static void main(String[] args) {
HashMap<String, Integer> hm = new HashMap<String, Integer>();
// put() 메소드를 이용한 요소의 저장
hm.put("삼십", 30);
hm.put("십", 10);
hm.put("사십", 40);
hm.put("이십", 20);
// Enhanced for문과 get() 메소드를 이용한 요소의 출력
// Set keySet() : HashMap에서 모든 키가 저장된 Set을 반환
System.out.println("맴에 저장된 키들의 집합 : "+hm.keySet());
for(String key:hm.keySet()) {
System.out.println(String.format("키:%s, 값:%s", key, hm.get(key)));
}System.out.println();
// remove() 메소드를 이용한 요소의 제거
hm.remove("사십"); // key값
// iterator() 메소드와 get() 메소드를 이용한 요소의 출력
Iterator<String> keys = hm.keySet().iterator();
while(keys.hasNext()) {
String key = keys.next();
System.out.println(String.format("키:%s, 값:%s", key, hm.get(key)));
}System.out.println();
// replace() 메소드를 이용한 요소의 수정
hm.replace("이십", 200);
for(String key:hm.keySet()) {
System.out.println(String.format("키:%s, 값:%s", key, hm.get(key)));
}System.out.println();
// size() 메소드를 이용한 요소의 총 개수
System.out.println("맵의 크기 : "+hm.size());
}
}
/* 출력결과
맴에 저장된 키들의 집합 : [이십, 삼십, 사십, 십]
키:이십, 값:20
키:삼십, 값:30
키:사십, 값:40
키:십, 값:10
키:이십, 값:20
키:삼십, 값:30
키:십, 값:10
키:이십, 값:200
키:삼십, 값:30
키:십, 값:10
맵의 크기 : 3
*/
2) TreeMap <K, V> Class - 범위 검색과 정렬에 유리
- TreeMap 클래스는 키와 값으로 저장되어 범위 검색과 정렬에 유리한 이진 검색 트리(binary search tree)로 구현
- TreeSet처럼 데이터를 정렬(키)해서 저장하기때문에 저장시간이 길다. (TreeSet은 TreeMap을 이용해 구현)
- Map이 필요할때는 주로 HashMap을 이용하고, 정렬이나 범위검색이 필요한 경우에 TreeMap을 이용
-
Map.Entry<K,V> ceilingEntry(K key) : 해당 맵에서 전달된 키와 같거나, 전달된 키보다 큰 키 중에서 가장 작은 키와 그에 대응하는 값의 엔트리를 반환함. 만약 해당하는 키가 없으면 null을 반환함
-
K ceilingKey(K key) : 당 맵에서 전달된 키와 같거나, 전달된 키보다 큰 키 중에서 가장 작은 키를 반환함. 만약 해당하는 키가 없으면 null을 반환함
-
void clear() : 해당 map의 모든 mapping 제거
-
boolean containsKey(Object key) : 해당 맵이 전달된 키를 포함하고있는지 확인
-
boolean containsValue(Object value) : 해당 맵이 전달된 값에 해당하는 하나 이상의 키를 포함하고있는지 확인
-
NavigableMap<K,V> descendingMap() : 해당 맵에 포함된 모든 매핑을 역순으로 반환
-
Set<Map.Entry<K,V>> entrySet() : 해당 맵에 포함된 모든 매핑을 Set 객체로 반환
-
Map.Entry<K,V> firstEntry() : 해당 맵에서 현재 가장 작은(첫 번째) 키와 그에 대응하는 값의 엔트리 반환
-
K firstKey() : 해당 맵에서 현재 가장 작은(첫 번째) 키를 반환
-
Map.Entry<K,V> floorEntry(K key) : 해당 맵에서 전달된 키와 같거나, 전달된 키보다 작은 키 중에서 가장 큰 키와 그에 대응하는 값의 엔트리를 반환함. 만약 해당하는 키가 없으면 null 반환
-
K floorKey(K key) : 해당 맵에서 전달된 키와 같거나, 전달된 키보다 작은 키 중에서 가장 큰 키를 반환함. 만약 해당하는 키가 없으면 null 반환
-
V get(Object key) : 해당 맵에서 전달된 키에 대응하는 값을 반환함. 만약 해당 맵이 전달된 키를 포함한 매핑을 포함하고 있지 않으면 null을 반환
-
SortedMap<K, V> headMap(K toKey) : 해당 맵에서 전달된 키보다 작은 키로 구성된 부분만을 반환
-
Map.Entry<K, V> higherEntry(K key) : 해당 맵에서 전달된 키보다 작은 키 중에서 가장 큰 키와 그에 대응하는 값의 엔트리를 반환함. 만약 해당하는 키가 없으면 null을 반환
-
K higherKey(K key) : 해당 맵에서 전달된 키보다 작은 키 중에서 가장 큰 키를 반환함. 만약 해당하는 키가 없으면 null을 반환
-
Set<K> keySet() : 해당 맵에 포함되어 있는 모든 키로 만들어진 Set 객체를 반환
-
Map.Entry<K, V> lastEntry() : 해당 맵에서 현재 가장 큰(마지막) 키와 그에 대응하는 값의 엔트리를 반환
-
K lastKey() : 해당 맵에서 현재 가장 큰(마지막) 키를 반환
-
Map.Entry<K, V> lowerEntry(K key) : 해당 맵에서 전달된 키보다 큰 키 중에서 가장 작은 키와 그에 대응하는 값의 엔트리를 반환함. 만약 해당하는 키가 없으면 null을 반환
-
K lowerKey(K key) : 해당 맵에서 전달된 키보다 큰 키 중에서 가장 작은 키를 반환함. 만약 해당하는 키가 없으면 null을 반환
-
Map.Entry<K, V> pollFirstEntry() : 해당 맵에서 현재 가장 작은(첫 번째) 키와 그에 대응하는 값의 엔트리를 반환하고, 해당 엔트리를 맵에서 제거함
-
Map.Entry<K, V> pollLastEntry() : 해당 맵에서 현재 가장 큰(마지막) 키와 그에 대응하는 값의 엔트리를 반환하고, 해당 엔트리를 맵에서 제거함
-
V put(K key, V value) : 해당 맵에 전달된 키에 대응하는 값으로 특정 값을 매핑함
-
V remove(Object key) : 해당 맵에서 전달된 키에 대응하는 매핑을 제거함
-
boolean remove(K key, V value) : 해당 맵에서 특정 값에 대응하는 특정 키의 매핑을 제거함
-
V replace(K key, V value) : 해당 맵에서 전달된 키에 대응하는 값을 특정 값으로 대체함
-
boolean replace(K key, V oldValue, V newValue) : 해당 맵에서 특정 값에 대응하는 전달된 키의 값을 새로운 값으로 대체함
-
int size() : 해당 맵의 매핑의 총 개수를 반환
-
SortedMap<K, V> subMap(K fromKey, K toKey) : 해당 맵에서 fromKey부터 toKey까지로 구성된 부분만을 반환함. 이때 fromKey는 포함되나, toKey는 포함되지 않음
-
SortedMap<K, V> tailMap(K fromKey) : 해당 맵에서 fromKey와 같거나, fromKey보다 큰 키로 구성된 부분만을 반환함
package com.collection.java;
import java.util.Iterator;
import java.util.TreeMap;
public class ExTreeMap {
public static void main(String[] args) {
TreeMap<Integer,String> tm = new TreeMap<Integer, String>();
// put() 메소드를 이용한 요소의 저장
tm.put(30, "삼십");
tm.put(10, "십");
tm.put(40, "사십");
tm.put(20, "이십");
// Enhanced for문과 get() 메소드를 이용한 요소의 출력
System.out.println("맵에 저장된 키들의 집합 : "+tm.keySet());
for(Integer key:tm.keySet()) {
System.out.println(String.format("키 : %s, 값 : %s", key, tm.get(key)));
}System.out.println();
// remove() 메소드를 이용한 요소의 제거
tm.remove(40);
// iterator() 메소드와 get() 메소드를 이용한 요소의 출력
Iterator<Integer> keys = tm.keySet().iterator();
while(keys.hasNext()) {
Integer key = keys.next();
System.out.println(String.format("키 : %s, 값 : %s", key, tm.get(key)));
}System.out.println();
// replace() 메소드를 이용한 요소의 수정
tm.replace(20, "twenty");
for(Integer key:tm.keySet()) {
System.out.println(String.format("키 : %s, 값 : %s", key, tm.get(key)));
}System.out.println();
// size() 메소드를 이용한 요소의 총 개수
System.out.println("맵의 크기 : "+tm.size());
}
}
/* 출력결과
맵에 저장된 키들의 집합 : [10, 20, 30, 40]
키 : 10, 값 : 십
키 : 20, 값 : 이십
키 : 30, 값 : 삼십
키 : 40, 값 : 사십
키 : 10, 값 : 십
키 : 20, 값 : 이십
키 : 30, 값 : 삼십
키 : 10, 값 : 십
키 : 20, 값 : twenty
키 : 30, 값 : 삼십
맵의 크기 : 3
*/
- 내부적으로 Hashtable을 사용하며, key와 value를 (String, String)으로 저장
- 주로 어플리케이션의 환경설정에 관련된 속성 저장에 사용됨
4. Stack & Queue (가장 기본적인 자료구조)
- List 컬렉션 클래스의 Vector 클래스를 상속받아, 전형적인 스택 메모리 구조의 클래스를 제공
- 스택 메모리 구조는 선형 메모리 공간에 데이터를 저장하며, 후입선출(LIFO)의 시멘틱을 따르는 자료 구조
- 가장 나중에 저장된(push) 데이터가 가장 먼저 인출(pop)되는 구조
-> 더욱 복잡하고 빠른 스택을 구현하고 싶다면 Deque 인터페이스를 구현한 ArrayDeque 클래스를 구현하기
-
Deque<Integer> st = newArrayDeque<Integer>();
-> Stack 클래스는 스택 메모리 구조를 표현하기 위해, Vector 클래스의 메소드를 5개만 상속받아 사용함
-
boolean empty() : 해당 스택이 비어 있으면 true / 비어 있지 않으면 false 반환
-
E peek() : 해당 스택의 제일 상단에 있는(제일 마지막에 저장된) 요소 반환
-
E pop() : 해당 스택의 제일 상단에 있는(제일 마지막에 저장된) 요소를 반환하고, 해당 요소를 스택에서 제거함
-
E push(E item) : 해당 스택의 제일 상단에 요소를 삽입함
-
int search(Object o) : 해당 스택에서 전달된 객체가 존재하는 위치의 인덱스를 반환함, 이때 인덱스는 제일 상단에 있는(제일 마지막에 저장된) 요소의 위치부터 0이 아닌 1부터 시작함
package com.collection.java;
//import java.util.Deque;
import java.util.Stack;
public class ExStack {
public static void main(String[] args) {
// 스택의 생성
Stack<Integer> st = new Stack<Integer>();
//Deque<Integer> st2 = new Deque<Integer>();
// push() 메소드를 이용한 요소의 저장
st.push(4);
st.push(3);
st.push(2);
st.push(1);
// peek() 메소드를 이용한 요소의 반환
System.out.println(st.peek());
System.out.println(st);
// pop() 메소드를 이요한 요소의 반환 및 제거
System.out.println(st.pop());
System.out.println(st);
// search() 메소드를 이용한 요소의 위치 검색
System.out.println(st.search(4));
System.out.println(st.search(3));
}
}
/* 출력결과
1
[4, 3, 2, 1]
1
[4, 3, 2]
3
2
*/
- 클래스로 구현된 스택과 달리 자바에서 큐 메모리 구조는 별도의 인터페이스 형태로 제공
- 스택 메모리 구조는 선형 메모리 공간에 데이터를 저장하며, 선입선출(FIFO)의 시멘틱을 따르는 자료 구조
- 가장 먼저 저장된(push) 데이터가 가장 먼저 인출(pop)되는 구조
-> Queue 인터페이스를 상속받는 하위 인터페이스는 다음과 같다.
-
Deque<E> : (덱)Stack과 Queue의 결합, 양끝에서 저장(offer)과 삭제(pop) 가능 - 구현 클래스(ArrayDeque, LinkedList)
-
PriorityQueue<E> : 우선 순위가 높은 것부터 꺼냄(null) 저장 불가 / 입력(3,2,4,1,5) -> 출력(1,2,3,4,5)
-
BlockingQueue<E> : 비어 있을 때 꺼내기와, 가득 차 있을 때 넣기를 지정된 시간동안 지연시킴(block) - 멀티쓰레드
-
TransferQueue<E>
-> 더욱 복잡하고 빠른 큐를 구현하고 싶다면 Deque 인터페이스를 구현한 ArrayDeque 클래스를 구현하기
-
Deque<Integer> qu = newArrayDeque<Integer>();
-> Queue 인터페이스는 큐 메모리 구조를 표현하기 위해, Collection 인터페이스 메소드만을 상속받아 사용한다.
-
boolean add(E e) : 해당 큐의 맨 뒤에 전달된 요소를 삽입하고 / 삽입에 성공하면 true를 반환하고, 큐에 여유 공간이 없어 실패하면 IllegalStateException 예외를 발생 시킴
-
E element() : 해당 큐의 맨 앞에 있는 (제일 먼저 저장된) 요소를 반환함
-
boolean offer(E e) : 해당 큐의 맨 뒤에 전달된 요소를 삽입함
-
E peek() : 해당 큐의 맨 앞에 있는(제일 먼저 저장된) 요소를 반환 / 큐가 비어있으면 null을 반환함
-
E poll() : 해당 큐의 맨 앞에 있는(제일 먼저 저장된) 요소를 반환하고, 해당 요소를 큐에서 제거함 / 큐가 비어있으면 null을 반환함
-
E remove() : 해당 큐의 맨 앞에 있는(제일 먼저 저장된) 요소를 제거함
package com.collection.java;
//import java.util.ArrayDeque;
//import java.util.Deque;
import java.util.LinkedList;
public class ExQueue {
public static void main(String[] args) {
// 큐의 생성
LinkedList<String> qu = new LinkedList<String>();
//Deque<String> qu2 = new ArrayDeque<String>();
// add() 메소드를 이용한 요소의 저장
qu.add("넷");
qu.add("둘");
qu.add("셋");
qu.add("하나");
// peek() 메소드를 이용한 요소의 반환
System.out.println(qu.peek());
System.out.println(qu);
// poll() 메소드를 이용한 요소의 반환 및 제거
System.out.println(qu.poll());
System.out.println(qu);
// remove() 메소드를 이용한 요소의 제거
qu.remove("하나");
System.out.println(qu);
}
}
/*출력결과
넷
[넷, 둘, 셋, 하나]
넷
[둘, 셋, 하나]
[둘, 셋]
*/
컬렉션에 저장된 요소를 읽어오는 방법
1) Iterator<E> interface -> 반복자, 단방향
- 자바의 컬렉션 프레임워크는 컬렉션에 저장된 요소를 읽어오는 방법을 Iterator 인터페이스로 표준화하고 있다.
- Collection 인터페이스에서는 Iterator 인터페이스를 구현한 클래스의 인스턴스를 반환하는 iterator() 메소드를 정의하고 있음
- Collection 인터페이스를 상속받는 List와 Set 인터페이스에서도 iterator() 메소드 사용 가능
- 현재 자바에서는 될 수 있으면 JDK 1.5부터 추가된 향상된 for문인 Enhanced for문[ for(declaration : expression) ]을 사용하도록 권장하고 있다. 같은 성능을 유지하면서도 코드의 명확성을 확보하고 발생할 수 있는 버그를 예방해줄 수 있는데, 요소의 선택적 제거나 대체 등을 수행하기 위한 경우에는 iterator를 사용해야 한다.
-
boolean hasNext() : 읽어 올 요소가 남아있는지 확인한다. 있으면 true 없으면 false를 반환한다.
-
Object next() : 다음 요소를 읽어온다. next()를 호출하기 전 hasNext()를 호출하여 요소가 있는지 확인하는 것이 안전하다.
-
default void remove() : next()로 읽어온 요소를 삭제한다. next()를 호출한 다음에 remove()를 호출해야한다.(선택적 기능)
-
void forEachRemaining(Consumer<? super E> action) : 컬렉션에 남아있는 요소들에 대해 지정된 작업(action)을 수행한다. 람다식을 사용하는 디폴트 메소드(JDK 1.8부터 추가)
package com.collection.java;
import java.util.Iterator;
import java.util.LinkedList;
public class ExIterator {
public static void main(String[] args) {
LinkedList<Integer> lk = new LinkedList<Integer>();
lk.add(4);
lk.add(3);
lk.add(2);
lk.add(1);
Iterator<Integer> iter = lk.iterator();
while(iter.hasNext()) {
System.out.println(iter.next()+" ");
}
}
}
/* 출력결과
4
3
2
1
*/
JDK 1.0부터 사용해 온 Iterator 인터페이스와 같은 동작을 하는 인터페이스로 현재는 기존 코드와의 호환성을 위해서만 남아있다.
Enumeration 인터페이스보다는 Iterator 인터페이스를 사용하는 것이 좋다.
3) ListIterator<E> interface -> Iterator 상속, 양방향
- JDK 1.2 부터 제공되어 Iterator 인터페이스를 상속받아 여러 기능을 추가한 인터페이스
- 컬렉션 요소의 대체, 추가, 인덱스 검색 등을 위한 작업에서 양방향으로 이동하는 것을 지원
- List 인터페이스를 구현한 List 컬렉션 클래스에서만 ListIterator() 메소드를 통해 사용할 수 있음
-
void add(E e) : 해당 리스트(list)에 전달된 요소를 추가함(선택적 기능)
-
boolean hasNext() : 반복자가 해당 리스트를 순방향으로 순회할 때, 다음 요소를 가지고 있으면 true를 반환하고 없으면 false 반환
-
boolean hasPrevious() : 반복자가 해당 리스트를 역방향으로 순회할 때, 다음 요소를 가지고 있으면 true를 반환하고 없으면 false 반환
-
E next() : 리스트의 다음 요소를 반환하고, 커서(cursor)의 위치를 순방향으로 이동시킴
-
int nextIndex() : 다음 next() 메소드를 호출하면 반환될 요소의 인덱스를 반환
-
E previous() : 리스트의 이전 요소를 반환하고, 커서의 위치를 역방향으로 이동시킴
-
int previousIndex() : 다음 previousIndex() 메소드를 호출하면 반환될 요소의 인덱스를 반환
-
void remove() : next()나 previous() 메소드에 의해 반환된 가장 마지막 요소를 리스트에서 제거(선택적 기능)
-
void set(E e) : next()나 previous() 메소드에 의해 반환된 가장 마지막 요소를 전달된 객체로 대체(선택적 기능)
package com.collection.java;
import java.util.LinkedList;
import java.util.ListIterator;
public class ExListIterator {
public static void main(String[] args) {
LinkedList<Integer> lk = new LinkedList<Integer>();
lk.add(4);
lk.add(3);
lk.add(2);
lk.add(1);
ListIterator<Integer> iter = lk.listIterator();
// 순방향
while(iter.hasNext()) {
System.out.println(iter.next()+" ");
}
System.out.println();
// 역방향
while(iter.hasPrevious()) {
System.out.println(iter.previous()+" ");
}
}
}
/* 출력결과
4
3
2
1
1
2
3
4
*/
객체를 정렬하는 인터페이스
- 자바에서 같은 타입의 인스턴스를 서로 비교해야만 하는 클래스들이 모두 구현하는 인터페이스
- Boolean을 제외한 래퍼 클래스, String, Time, Date와 같은 클래스의 인스턴스는 모두 정렬 가능
- 정렬의 기본 순서는 오름차순
-
int compareTo(T o) : 해당 객체와 전달된 객체의 순서를 비교함
package com.collection.java;
class Car implements Comparable<Car>{
private String modelName;
private int modelYear;
private String color;
Car(String mn, int my, String c){
this.modelName=mn;
this.modelYear=my;
this.color=c;
}
public String getModel() {
return this.modelYear+"식 "+this.modelName+" "+this.color;
}
public int compareTo(Car obj) {
if(this.modelYear==obj.modelYear) {
return 0;
}else if(this.modelYear<obj.modelYear) {
return -1;
}else {
return 1;
}
}
}
public class ExComparable{
public static void main(String[] args) {
Car car1 = new Car("아반떼",2020,"노란색");
Car car2 = new Car("소나타",2021,"빨간색");
System.out.println(car1.compareTo(car2));
System.out.println(car1.getModel());
System.out.println(car2.getModel());
}
}
/* 출력결과
-1
2020식 아반떼 노란색
2021식 소나타 빨간색
*/
- Comparable 인터페이스와 같이 객체를 정렬하는 데 사용되는 인터페이스
- Comparable과 달리 내림차순이나 다른 기준으로 정렬하고싶을 때 사용
- Compare() 메소드를 재정의하여 사용하게됨
-
int compare(T o1, T o2) : 전달된 두 객체의 순서를 비교함
-
boolean equals(Object obj) : 해당 comparator와 전달된 객체가 같은지를 확인함
-
default Comparator<T> reversed() : 해당 comparator의 역순인 comparator를 반환함
package com.collection.java;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
class DescendingOrder implements Comparator<Integer>{
public int compare(Integer o1, Integer o2) {
if(o1 instanceof Comparable && o2 instanceof Comparable) {
Integer c1 = (Integer)o1;
Integer c2 = (Integer)o2;
return c2.compareTo(c1);
}
return -1;
}
}
public class ExComparator{
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<Integer>(new DescendingOrder());
ts.add(30);
ts.add(40);
ts.add(20);
ts.add(10);
Iterator<Integer> iter = ts.iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
}
}
/* 출력결과
40
30
20
10
*/
컬렉션 알고리즘(Collection Algorithm)
Collections 클래스는 모든 컬렉션의 알고리즘을 담당한다.
유틸리티 클래스로써 static 메소드로 구성되어 있고 컬렉션들을 컨트롤하는 데에 사용된다.
주의할 점은 자바의 Collection은 인터페이스이며, Collections는 클래스라는 점이다.
-
정렬(Sorting) : 정렬 알고리즘은 요소가 오름차순이 되도록 리스트를 재 정렬함
-
셔플링(Shuffling) : 셔플링 알고리즘은 랜덤으로 목록을 재 정렬함(우연한 게임을 구현할 때 유용)
-
탐색(Searching) : 이진 검색 알고리즘은 정렬된 목록에서 지정된 요소를 검색
컬렉션 프레임워크의 올바른 사용법(필요에 따라 상황에 맞게 컬렉션 선택)
Collections 클래스는 모든 컬렉션의 알고리즘을 담당한다.
-
크기(size)가 고정되어 있다면 ArrayList보다 Array를 사용하기
-
맵에 삽입된 순서대로 iterate를 하고 싶으면 TreeMap을 사용하기
-
중복을 허용하고 싶지 않으면 Set을 사용하기
-
몇몇 컬렉션 클래스들은 초기 용량을 지정할 수 있는데, 만약 저장할 요소들의 사이즈를 알 경우에는 초기 용량을 지정함으로써 rehashing이나 resizing이 일어나는 것을 피할 수 있음
-
코드를 작성할 때, 구현 클래스가 아닌 인터페이스를 기반으로 작성해야 나중에 구현체를 변경할 때 코드를 재작성하는 수고를 줄일 수 있음
-
런타임에 발생할 수 있는 ClassCastException을 피하려면 항상 제네릭(Generics)을 사용해 type-safety 상태 만들기
-
맵에 키를 사용할 때 JDK에서 제공하는 immutable 클래스(heap영역에서의 변경 불가)를 사용하여 사용자 클래스에서 hashCode()와 equals()를 구현할 필요가 없게하기
-
읽기 전용 및 동기화, 빈 컬렉션 등을 만들 때에는 자신만의 구현 방식으로 생성하지않고 Collections에서 제공하는 유틸리티 클래스를 사용하여 안정적으로 코드 재사용성을 높이며 유지보수 비용 줄이기
출처 및 참고
https://docs.oracle.com/javase/tutorial/collections/index.html
http://www.falkhausen.de/Java-8/java.util/Collection-Hierarchy.html
'Programming > Java' 카테고리의 다른 글
DTO vs VO vs Entity (0) | 2020.08.14 |
---|---|
[JAVA] 자바의 스트림(stream)과 파일 입출력 (0) | 2020.08.14 |
[Java / Spring ] 어노테이션(@, annotation)의 정의와 종류 (0) | 2020.08.12 |
[JAVA] 제네릭(Generic) (0) | 2020.08.02 |
[JAVA] Iterator method : hasNext() vs next() 메소드 차이점 (0) | 2020.07.25 |