JCF(Java Collections Framework)
데이터, 자료구조인 컬렉션과 이를 구현하는 클래스를 정의하는 인터페이스를 제공
사용할때는 기본형 변수가 아닌 참조형 변수를 사용해야한다
아래 사진은 상속구조를 보여주는 사진
map의 경우에는 collection 인터페이스를 상속받고 있지 않지만 collection으로 분류// Collection을 사용하는 이유
1. Collection의 일관된 API를 사용하여 모든 클래스가 Collection에서 상속받아 통일된 메서드를 사용
2. 객체지향프로그래밍의 추상화가 성공적으로 구현
■ Collection 인터페이스의 특징
| 인터페이스 | 구현클래스 | 특징 |
|---|---|---|
| Set | HashSet | |
| TreeSet | 순서를 유지하지 않는 데이터의 집합으로 데이터의 중복을 허용하지 않는다. | |
| List | LinkedList |
// Vector는 동기화가 이미되어있는 클래스로 한번에 하나의 쓰레드만 접근 가능
// Arraylist는 동기화처리가 안된 클래스로 동시에 여러쓰레드에 접근이 가능// ArrayList
// List
// array와 다른점 -> 처음에 길이를 몰라도 만들수있다
// Array -> 정적배열
// List(ArrayList) -> 동적배열(크기가 가변적으로 늘어남)
// - 생성 시점에 작은 연속된 공간을 요청해서 참조형 변수들을 담아놓는다
// - 값이 추가될 때 더 큰 공간이 필요한면 더 큰 공간을 받아서 저장함
// 표준 배열보다 느릴수도있지만 움직이이 많은 배열에서 유용
// ArrayList import를 해주어야함
ArrayList<Integer> intList = new ArrayList<Integer>(); // 선언과 생성
intList.add(1); // 값 추가
intList.add(12); // 값 추가
intList.add(123); // 값 추가
System.out.println(intList.get(0)); // 첫번째로 집어넣은 값 가져오기
intList.set(1,22); // 1번째 index위치에있는값을 22로 변환
System.out.println(intList.get(1)); // 22
intList.remove(1); // index번호의 값을 삭제
System.out.println(intList.get(1)); // 123 -> 22번값이 삭제되어 123번이 1번째 index위치로 땅겨져옴
System.out.println(intList.toString()); // list안의값 전부 가져오기
intList.clear(); // 해당 list 초기화
System.out.println(intList.toString()); // list안의값 전부 가져오기// linked list
// 메모리에 남는 공간을 요청해서 여기 저기 나누어서 실제 값을 담아둠
// 실제 값이 있는 주소값으로 목록을 구성하고 저장하는 자료구조
// 기본적 기능 -> ArrayList와 동일
// LinkedList는 값 -> 여기 저기 나누어서 값을 넣었기때문에 조회하는 속도가 느리다
// 값을 추가 하거나 삭제할때는 빠르다
// 이유로는 ArrayList처럼 순서가 있는 경우에는 순서하나하나를 확인하지마
// Linked List의 경우에는 비어있는 값에가서 그냥 저장 삭제를 하기때문에
LinkedList<Integer> linkedList = new LinkedList<Integer>();
// LinkedList<Integer> linkedList = new LinkedList<>(); // 생성시 타입생략가능
linkedList.add(1);
linkedList.add(122);
linkedList.add(1333);
System.out.println(linkedList.get(0));
System.out.println(linkedList.get(1));
System.out.println(linkedList.get(2));
System.out.println(linkedList.toString()); // arraylist보다 속도가 느림
// arraylist와 다른점
// add를 할때 index위치를 지정할수있다
linkedList.add(1,4444); // 1번째 index에 4444값을 추가
System.out.println(linkedList.toString()); // 추가 삭제는 빠르다
linkedList.set(2,5555);
System.out.println(linkedList.toString());
linkedList.remove(2);
System.out.println(linkedList.toString());
linkedList.clear();
System.out.println(linkedList.toString());// Vector
// ArrayList와 유사
// 차이점으로는 Vector는 동기화가되고, ArrayList는 안됨
// Vector는 동기화가 이미되어있는 클래스로 한번에 하나의 쓰레드만 접근 가능
// Arraylist는 동기화처리가 안된 클래스로 동시에 여러쓰레드에 접근이 가능
mport java.io.*;
import java.util.*;
class GFG {
public static void main(String[] args)
{
// Vector 선언
Vector<Integer> v
= new Vector<Integer>();
// 데이터 입력
for (int i = 1; i <= 5; i++)
v.add(i);
// 결과 출력
System.out.println(v);
// 3번 데이터 삭제
v.remove(3);
// 결과 출력
System.out.println(v);
// 하나씩 결과 출력
for (int i = 0; i < v.size(); i++)
System.out.print(v.get(i) + " ");
}
}// Stack
// 수직을 값을 쌓아놓고, 넣었다가 뺀다 filo
// push(넣기),peek(조회),pop(삭제)
// 최근 저장된 데이터를 나열하거나 데이터 중복 처리를 막고 싶을때
Stack<Integer> intStack = new Stack<Integer>();
intStack.push(12);
intStack.push(1222);
intStack.push(124444);
// 다 지워질때까지 출력
while(!intStack.isEmpty()){
// isEmpty() -> 공백일때 true
// 위의 조건은 !이 있으니까 값이 있을때 true반환
System.out.println(intStack.pop());
// 제일 위에있는 값이 조회되면서 빠져나옴
// 지금같이 3개가 있는경우 3번돌아감
}
intStack.push(12333);
intStack.push(12);
intStack.push(1);
System.out.println(intStack.peek());
// 가장 마지막에 들어감 값인 1이들어감 / 맨위값을조회
System.out.println(intStack.size());
// 길이
// 스택 인덱스의 값 확인
// 스택.elementAt(인덱스);
// 스택 특정 값이 어느 인덱스에 들었나 확인
// 스택.indexOf("값");// Queue : fifo
// add, peek, poll
// Queue : 생성자가 없는 인터페이스
Queue<Integer> intQueue = new LinkedList<Integer>();
intQueue.add(1);
intQueue.add(12);
intQueue.add(31);
while (!intQueue.isEmpty()){
System.out.println(intQueue.poll());
// stack과 다르게 들어간순서대로 나옴
}
intQueue.add(1);
intQueue.add(12);
intQueue.add(31);
System.out.println(intQueue.peek());
System.out.println(intQueue.size());
intQueue.add(3133);
System.out.println(intQueue.size());// set : 집합 순서 없고, 중복 없음
// set -> 그냥 사용할수도있고, HashSet,TreeSet등으로 응용해서도 사용 가능
// set은 생성자가 없는 인터페이스
// 바로 생성 불가능
// HashSet은 생성자가 존재
Set<Integer> intSet = new HashSet<Integer>();
intSet.add(11);
intSet.add(112);
intSet.add(1133);
intSet.add(11);
for(Integer value : intSet){
System.out.println(value);
// 11이 중복되어서 세번만 반복됨
}
// contains
// 해당값을 포함 하고있는지 여부확인 reture값 true/false
System.out.println(intSet.contains(2));
System.out.println(intSet.contains(233));// 처음설정은 오름차순
TreeSet<자료형> 변수명 = new TreeSet<>();
// 내림차순
TreeSet<자료형> 변수명 = new TreeSet<>(Collections.reverseOrder);
TreeSet<Integer> tSet = new TreeSet<>();
| 연산 | 코드 | 반환 값 |
|---|---|---|
| 삽입 | tSet.add(삽입할 value); | 트리에 value가 저장되어있던 경우 = False트리에 value가 저장되어있지 않던 경우 = True |
| 삭제 | tSet.remove(삭제할 value); | 트리에 value가 저장되어있던 경우 = True트리에 value가 저장되어있지 않던 경우 = False |
| 모든 값 삭제 | tSet.clear(); | - |
| 크기 | tSet.size(); | 트리의 사이즈 |
| 전체 원소 집합 출력 | System.out.println(tSet); | [원소1, 원소2, ..., 원소n] |
| 정렬 순서 기준 맨 앞 원소 | tSet.first(); | 정렬 순서 기준 맨 앞 원소 |
| 정렬 순서 기준 맨 뒤 원소 | tSet.last(); | 정렬 순서 기준 맨 뒤 원소 |
| value보다 큰 원소들 중 최솟값 | tSet.higher(value); | value보다 큰 원소들 중 최솟값 |
| value보다 작은 원소들 중 최댓값 | tSet.lower(value); | value보다 작은 원소들 중 최댓값 |
| 트리가 비어있는지 확인 | tSet.isEmpty(); | 트리의 사이즈가 0이면 = True트리의 사이즈가 0보다 크면 = False |
| 트리에 value가 저장되어 있는지 | tSet.contains(value); | 트리에 value가 저장되어있는 경우 = True트리에 value가 저장되어있지 않은 경우 = False |
엘리멘트들을 정렬된 순서로 저장
저장되는 엘리먼트가 Comparable 인터페이스를 구현하고 있다면 compare()메서드의 로직을 이용
구현체를 생성할 때 Comparator 클래스를 넘겨 엘리먼트들의 대소 비교에 사용가능
SortedSet<String> sortedSet = new TreeSet<>();
// sortedSet.add("Elem5");
// sortedSet.add("Elem3");
// sortedSet.add("Elem1");
// sortedSet.add("Elem3");
// sortedSet.add("Elem1");
//
// for (String elem : sortedSet) {
// System.out.println(elem);
// // 중복값은 제거되고 1,3,5순으로 정렬되서 나옴
// }
sortedSet.add("Elem5");
sortedSet.add("Elem2");
sortedSet.add("Elem4");
sortedSet.add("Elem3");
sortedSet.add("Elem1");
// SortedSet<String> headSet = sortedSet.headSet("Elem3");
// System.out.println("Head Set");
// for (String elem : headSet) {
// System.out.println(elem);
// // Elem3값을 넣어주었기때문에
// // 끝값인 3전까지 출력
// // 1,2가 나옴
// }
// SortedSet<String> tailSet = sortedSet.tailSet("Elem4");
// System.out.println("Tail Set");
// for (String elem : tailSet) {
// System.out.println(elem);
// // Elem4부터 이후로의 값이 나옴
// }
//
// SortedSet<String> subSet = sortedSet.subSet("Elem2", "Elem5");
// System.out.println("Sub Set");
// for (String elem : subSet) {
// System.out.println(elem);
// // 2부터 5사이의 값이 나옴
// // 마지막 값은 포함안됨
// }
System.out.println(sortedSet.first()); // 첫번째 값만
System.out.println(sortedSet.last()); // 마지막 값만
Hashtable
HashMap
TreeMap
- 정렬된 순서대로 키(Key)와 값(Value)을 저장하여 검색이 빠름
// Map : key - value pair -> 중요
// key라는 값으로 unique하게 보장이 되어야함
// Map -> HashMap,TreeMap으로 응용
Map<String,Integer> intmap = new HashMap<>();
// 키 값
intmap.put("일",1);
intmap.put("이",2);
intmap.put("삼",3);
intmap.put("사",4);
intmap.put("오",5);
intmap.put("오",6);
for(String key : intmap.keySet()){
// .keySet() : key값만 가져옴
System.out.println(key); // 중복된 key는 생략되어서 하나만 나옴
}
for(Integer value : intmap.values()){
// .values() : values값만 가져옴
System.out.println(value); // 중복된 값중에서 가장 마지막으로 들어간 값이 나옴
}
System.out.println(intmap.get("이")); // key값으로 value값 찾아오기
Map출력방법
Map에 값을 전체 출력하기 위해서는 entrySet(), keySet() 메소드를 사용하면 되는데 entrySet() 메서드는 key와 value의 값이 모두 필요한 경우 사용하고, keySet() 메서드는 key의 값만 필요한 경우 사용
방법 01. entrySet()
Map<String, String> map = new HashMap<>();
map.put("key01", "value01");
map.put("key02", "value02");
map.put("key03", "value03");
map.put("key04", "value04");
map.put("key05", "value05");
// 방법 01 : entrySet()
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("[key]:" + entry.getKey() + ", [value]:" + entry.getValue());
}
방법 02. keySet()
Map<String, String> map = new HashMap<>();
map.put("key01", "value01");
map.put("key02", "value02");
map.put("key03", "value03");
map.put("key04", "value04");
map.put("key05", "value05");
// 방법 02 : keySet()
for (String key : map.keySet()) {
String value = map.get(key);
System.out.println("[key]:" + key + ", [value]:" + value);
}
방법 03. entrySet().iterator()
Iterator 인터페이스를 사용할 수 없는 컬렉션인 Map에서 Iterator 인터페이스를 사용하기 위해서는 Map에 entrySet(), keySet() 메소드를 사용하여 Set 객체를 반환받은 후 Iterator 인터페이스를 사용
Map<String, String> map = new HashMap<>();
map.put("key01", "value01");
map.put("key02", "value02");
map.put("key03", "value03");
map.put("key04", "value04");
map.put("key05", "value05");
// 방법 03 : entrySet().iterator()
Iterator<Map.Entry<String, String>> iteratorE = map.entrySet().iterator();
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);
}
방법 04. keySet().iterator()
Map<String, String> map = new HashMap<>();
map.put("key01", "value01");
map.put("key02", "value02");
map.put("key03", "value03");
map.put("key04", "value04");
map.put("key05", "value05");
// 방법 04 : keySet().iterator()
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);
}
방법 05. Lambda 사용
Map<String, String> map = new HashMap<>();
map.put("key01", "value01");
map.put("key02", "value02");
map.put("key03", "value03");
map.put("key04", "value04");
map.put("key05", "value05");
// 방법 05 : Lambda 사용
map.forEach((key, value) -> {
System.out.println("[key]:" + key + ", [value]:" + value);
});
방법 06. Stream 사용
Map<String, String> map = new HashMap<>();
map.put("key01", "value01");
map.put("key02", "value02");
map.put("key03", "value03");
map.put("key04", "value04");
map.put("key05", "value05");
// 방법 06 : Stream 사용
map.entrySet().stream().forEach(entry-> {
System.out.println("[key]:" + entry.getKey() + ", [value]:"+entry.getValue());
});
// Stream 사용 - 내림차순
map.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry-> {
System.out.println("[key]:" + entry.getKey() + ", [value]:"+entry.getValue());
});
// Stream 사용 - 오름차순
map.entrySet().stream().sorted(Map.Entry.comparingByKey(Comparator.reverseOrder())).forEach(entry-> {
System.out.println("[key]:" + entry.getKey() + ", [value]:"+entry.getValue());
});
// ArrayList와 동일한 내부구조
// ArrayList와 다르게 동기화된 메소드로 구성
// 멀티 스레드가 동시에 이 메서드를 실행할 수 없고,하나의 스레드가 실행을 완료해야만 다른 스레드들이 실행할 수 있다
// 멀티 스레드 환경에서 안전하게 객체를 추가 삭제가 가능
// 항상 동기화 되기때문에 스레드가 하나여도 동기화를 한다
// 그렇기 때문에 ArrayList보다 성능이 떨어진다
// ArrayList는 자동 동기화기능은 없고 옵션으로 존재한다
// 그리고 벡터보다 속도가 빠르기 때문에 ArrayList를 더많이 사용한다 
// 선언
// 타입을 지정하지 않고 임의의 타입의 값을 넣고 사용할 수도 있지만
// 벡터 내부의 값을 사용하려면 캐스팅(Casting)연산이 필요하며 잘못된 타입으로 캐스팅을 한 경우에는 에러가 발생할 수 도 있다
// 그렇기 때문에 사용시 타입명시를 하는게 좋다
Vector v = new Vector();//타입 미설정 Object로 선언된다.
Vector<Student> student = new Vector<Student>(); //타입설정 Student객체만 사용가능
Vector<Integer> num2 = new Vector<Integer>(); //타입설정 int타입만 사용가능
Vector<Integer> num3 = new Vector<>(); //new에서 타입 파라미터 생략가능
Vector<String> v2 = new Vector<String>(10);//초기 용량(capacity)지정
Vector<Integer> v3 = new Vector<Integer>(Arrays.asList(1,2,3)); //초기값 지정// 값 추가
// 구조는 ArrayList와 LinkedList와 같다
// add(index,value)
// index를 사용하지않으면 맨뒤에 값이 추가된다
Vector<Integer> v = new Vector<Integer>();
v.add(3); //값 추가
v.add(null); //null값도 add가능
v.add(1,10); //index 1뒤에 10 삽입
Vector v = new Vector();
Student student = new Student(name,age);
v.add(student);
v.add(new Member("홍길동",15));// 값 삭제
Vector<Integer> v = new Vector<Integer>(Arrays.asList(1,2,3));
v.remove(1); //index 1 제거
v.removeAllElements(); //모든 값 제거
v.clear(); //모든 값 제거// 크기 구하기
Vector<Integer> v = new Vector<Integer>(10);//초기용량 10
v.add(1); //값 추가
System.out.println(v.size()); //Vector 자료 개수 : 1
System.out.println(v.capacity()); //Vector 물리적크기 : 10// 값 출력
Vector<Integer> list = new Vector<Integer>(Arrays.asList(1,2,3));
System.out.println(list.get(0));//0번째 index 출력
for(Integer i : list) { //for문을 통한 전체출력
System.out.println(i);
}
Iterator iter = list.iterator(); //Iterator 선언
while(iter.hasNext()){//다음값이 있는지 체크
System.out.println(iter.next()); //값 출력
}