Set 인터페이스
- Collection 인터페이스를 확장한 인터페이스로 순서에 상관없이 데이터 존재 여부를 확인하기 위한 용도로 사용한다.
- 중복되는 것을 방지, 원하는 값이 포함되어 있는지를 확인하는 것이 주 목적.
- 데이터 추가 시 자동으로 데이터가 중복되지 않고 저장된다.
- Set 인터페이스를 구현한 클래스
- HashSet : 순서가 전혀 필요없는 데이터를 HashTable에 저장하며 Set 중 가장 성능이 좋다. (별도의 정렬 작업x)
- TreeSet : 저장된 데이터의 값에 따라서 정렬되는 Set, red-black이라는 tree타입으로 저장된다.
- LinkedHashSet : 연결된 목록 타입으로 구현된 HashTable에 데이터 저장, 저장된 순서에 따라 값이 정렬되며 성능이 가장 나쁘다.
- 성능 차이가 발생하는 이유는 데이터 정렬 때문
red-black tree : 각 노드의 색을 붉은색 / 검은색으로 구분해 데이터를 빠르고 쉽게 찾을 수 있는 이진트리
- Set은 데이터가 중복되는 것을 허용하지 않기에 데이터가 같은지 확인하는 작업은 Set의 핵심
- Object 클래스에서 equals(), hashCode() 메소드만 구현했다.
- Set에서는 List와 달리 index를 매개 변수로 넘기는 메소드, 결과를 index와 관련되어 리턴하는 메소드는 필요가 없다.
HashSet 클래스
- 순서가 필요 없는 데이터를 저장하기에 정렬 작업이 필요 없어서 Set 중 성능이 가장 좋다.
- 여러 중복되는 값들을 걸러내기에 매우 유용하다.
- HashSet 클래스의 생성자
- HashSet() : 데이터를 저장할 수 있는 16개 공간과 0.75의 로드 팩터(load factor)를 갖는 객체를 생성한다.
- HashSet(int initialCapacity) : initialCapacity 만큼의 데이터 저장 곤간과 0.75 로드 팩터를 갖는 객체를 생성한다.
- 그 외에도 2개의 생성자가 더 존재하지만 지금 수준에서는 잘 사용하지 않기에 패스....
load factor : 데이터 개수 / 저장 공간을 의미한다.
데이터 개수가 증가해 로드 팩터보다 커지면 저장 공간의 크기는 증가되고 해시 재정리 작업(refresh)를 해야한다.
refresh 작업을 하는 경우 내부에 있는 자료 구조를 다시 생성해야 하기에 성능에 영향을 미친다.
초기 저장 공간과 로드 팩터는 데이터 크기를 적절히 고려해 산정해야한다.
- HashSet을 사용하기 위해서
import java.util.HashSet;
import java.util.Set; 이 필요하다. - HashSet 클래스의 메소드
- boolean add (E e) : 데이터를 추가한다.
- void clear() : 모든 데이터를 삭제한다.
- Object clone() : HashSet 객체를 복제한다. (담겨 있는 데이터는 복제x)
- boolean contains(Object o) : 지정한 객체가 존재하는지 확인한다.
- boolean isEmpty() : 객체가 비어있는지 확인한다.
- Iterator<E> iterator() : 데이터를 꺼내기 위한 Iterator 객체를 리턴한다.
- boolean remove(Object o) : 지정된 객체를 삭제한다.
- int size() : 저장된 데이터 개수를 리턴한다.
- Set에 저장된 데이터를 꺼내는 방법
- for 루프를 사용해서 꺼내는 방식
- Iterator 객체를 얻어서 꺼내는 방식
HashSet<String> set = new HashSet<>(); //set에 데이터가 들어있다고 가정
//for 루프로 값을 꺼내는 방식
public void printCarSet(Set<String> set) {
for (String car : set) {
System.out.print(car + " ");
}
}
//Iterator 객체로 값을 꺼내는 방식
public void printCarSet2(Set<String> set) {
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
}
- Iterator 객체로 값을 꺼내는 방식
- Iterator를 사용하기 위해 import java.util.Iterator; 가 필요하다.
- hasNext()는 다음 값이 있는지 확인하는 메소드로 isEmpty()와 같은 기능
- next()는 다음 값을 얻어오고 삭제한다.
LinkedList 클래스
- LinkedList는 쉽게 생각하면 열차와 같은 구조를 가지고 있다.
- A - B - C - D - E - ... 구조
- 값은 서로 앞 뒤의 값만 기억하고 있는다. (자신과 연결된 값)
- 각 노드가 데이터와 포인터를 가지고 한 줄로 연결되어 있는 방식인 자료구조
- 다음 값만 가리키고 있다면 단일 연결리스트 (단방향 연결)
- 이전 값, 다음 값 모두 가리키고 있다면 다중 연결리스트 (양방향 연결)
- LinkedList는 List 인터페이스, Queue, Deque 인터페이스를 구현하고 있다.
- LinkedList는 List도 Queue도 된다.
- Queue는 FIFO 용도로 사용한다.
- First In First Out으로 선입선출 방식의 자료 구조
- 여러 쓰레드에서 들어오는 작업을 순차적으로 처리할 때 많이 사용한다.
- ex) 웹 서버에서 클라이언트 응답을 줄 때
- Deque은 "Double Ended Queue"의 약자로 deck과 같은 발음.
- Queue 인터페이스를 확장한 인터페이스로 Queue의 모든 기능과 더불어 맨 앞, 뒤에서 값을 넣거나 빼는 작업 수행이 용이하도록 되어 있다.
- LinkedList가 배열보다 메모리 공간 측면에서 훨씬 유리하다.
- 배열과 같은 Vector, ArrayList는 데이터의 각 index가 정해져 있고 그 index로 데이터를 찾는다.
- 그렇기에 맨 앞이나 중간의 값을 삭제하면 그 뒤의 값들은 전부 하나씩 앞으로 index를 이동해야한다.
- LinkedList는 중간에 있는 값을 삭제하면 삭제한 데이터 앞의 데이터와 뒤에 있는 데이터를 연결하면 된다.
- 위치를 맞추기 위해서 값을 이동하는 단계가 필요 없기에 메모리 공간 측면에서 훨씬 효율적.
- ex) A - B - C - D - E - F에서 C를 삭제 시 A - B - D - E - F 처럼 B와 D만 연결하면된다.
- 배열과 같은 Vector, ArrayList는 데이터의 각 index가 정해져 있고 그 index로 데이터를 찾는다.
- LinkedList 클래스의 생성자는 다른 클래스와 다르게 처음부터 크기를 지정하지 않는다.
- 각 데이터들이 앞 뒤로 연결되는 구조이기에 미리 공간을 만들어놓을 필요가 없다.
- LinkedList 클래스의 메소드는 구현하는 인터페이스가 많기에 중복되는 기능을 수행하는 메소드가 많다.
- LinkedList 클래스의 데이터를 추가하는 메소드
- void addFirst(Object) / push(Object): 객체의 가장 앞에 데이터를 추가한다.
boolean offerFirst(Object)- LinkedList에서 맨 앞에 추가하는 메소드를 사용해도 addFirst() 메소드를 호출한다.
- boolean add(Object) / offer(Object) / offerLast(Object) : 객체의 가장 뒤에 데이터를 추가한다.
void addLast(Object)
- LinkedList에서 맨 뒤에 추가하는 메소드를 사용해도 add()나 addLast() 메소드를 호출한다.
- void add(int, Object) : 객체의 특정 위치에 데이터를 추가한다.
- Object set(int, Object) : 객체의 특정 index에 있는 데이터를 수정하고 기존 데이터를 리턴한다.
- boolean addAll(Collection) : 매개 변수 컬렉션의 데이터를 추가한다.
- boolean addAll(int, Collection) : 특정 위치에 매개 변수 컬렉션의 데이터를 추가한다.
- 여러 메소드를 혼용 시 이해하기 힘들기에 한 가지만 선정하여 사용하는 것이 좋으며 add가 붙은 메소드를 사용하는 것이 오해의 소지가 가장 적다.
- void addFirst(Object) / push(Object): 객체의 가장 앞에 데이터를 추가한다.
- LinkedList의 객체를 System.out.println()으로 출력하면 객체에 들어있는 내용들이 순서대로 []안에 출력된다.
- LinkedList 클래스의 데이터를 조회하는 메소드
- Object getFirst() / peekFirst() / peek() / element() : 객체의 맨 앞에 있는 데이터를 리턴한다.
- 모두 getFirst() 메소드를 호출한다.
- getFirst() 사용을 권장한다.
- Object getLast() / peekLast() : 객체의 맨 뒤에 있는 데이터를 리턴한다.
- Object get(int) : 객체의 지정한 위치에 있는 데이터를 리턴한다.
- Object getFirst() / peekFirst() / peek() / element() : 객체의 맨 앞에 있는 데이터를 리턴한다.
- LinkedList 클래스의 어떤 객체가 포함되어 있는지 확인하는 메소드
- booelan contains(Object) : 매개 변수로 넘긴 객체가 존재할 경우 true 리턴
- int indexOf(Object) : 매개 변수 객체의 위치를 앞에서부터 검색해 리턴한다. 없을 경우 -1을 리턴한다.
- int lastIndexOf(Object) : 매개 변수 객체의 위치를 끝에서부터 검색해 리턴한다. 없을 경우 -1을 리턴한다.
- LinkedList 클래스의 데이터를 삭제하는 메소드는 대부분 객체에서 삭제하고 데이터를 리턴해주기 때문에 조회용 메소드보다 많이 사용한다.
- Object remove() / removeFirst() / poll() / pollFirst() / pop() : 객체의 가장 앞에 있는 데이터를 삭제하고 리턴한다.
- 모두 removeFirst() 메소드를 호출한다.
- Object pollLast() / removeLast() : 객체의 가장 끝에 있는 데이터를 삭제하고 리턴한다.
- 모두 removeLast() 메소드를 호출한다.
- Object remove(int) : 지정된 위치의 데이터를 삭제하고 리턴한다.
- boolean remove(Object) / removeFistOccurrence(Object) : 매개 변수 객체와 동일한 데이터 중 가장 앞에 있는 데이터를 삭제한다.
- boolean removeLastOccurrence(Object) : 매개 변수 객체와 동일한 데이터 중 가장 끝에 있는 데이터를 삭제한다.
- remove가 붙은 메소드를 사용할 것을 권장한다.
- Object remove() / removeFirst() / poll() / pollFirst() / pop() : 객체의 가장 앞에 있는 데이터를 삭제하고 리턴한다.
- LinkedList 클래스의 객체를 하나씩 검색하기 위한 메소드
- ListIterator listIterator(int) : 지정된 위치부터 데이터를 검색하기 위한 ListIterator 객체를 리턴한다.
- Iterator descendingIterator() : LinkedList 객체의 데이터를 끝에서부터 검색하기 위한 Iterator 객체를 리턴한다.
ListIterator : Iterator가 다음 데이터만 검색할 수 있다는 단점을 보완한 것으로 이전 데이터도 검색할 수 있는 Iterator다.
next() 외에도 previous() 메소드를 통해 이전 데이터를 확인할 수 있다.
간단 내용 정리
1. 순서와 상관 없는 여러 데이터를 하나의 객체에 저장할 때 사용하는 Collection의 하위 인터페이스는 무엇인가요?
Set
2. HashSet 클래스는 생성자를 통하여 저장 가능한 데이터의 초기 크기를 지정할 수 있나요?
O, LinkedList 클래스가 생성자를 통해 데이터의 초기 크기를 지정할 수 없다.
3. HashSet 클래스의 객체에 데이터를 추가하는 메소드는 무엇인가요?
add()
4. HashSet 클래스의 객체에 어떤 데이터가 존재하는지 확인하는 메소드는 무엇인가요?
contains()
5. HashSet 클래스의 객체에 어떤 데이터를 삭제하는 메소드는 무엇인가요?
remove()
6. Queue는 FIFO를 처리하기 위한 클래스들의 인터페이스 입니다. FIFO는 무슨 단어의 약어인가요?
First In First Out
7. Deque는 무슨 단어의 약어이며, 용도는 무엇인가요?
Double Ended Queue
8. LinkedList 클래스의 특징을 이야기해 봅시다.
각 노드가 데이터와 포인터를 가지고 한 줄로 연결되어 있는 방식으로 데이터를 저장하는 자료 구조이다.
데이터를 담고 있는 노드들이 연결되어 있는데, 노드의 포인터가 다음이나 이전의 노드와의 연결을 담당한다.
그렇기 때문에 중간에 있는 데이터를 삭제하더라도 삭제된 노드의 이전 노드와 다음 노드만 연결해주기에
index가 변하지 않아 메모리 공간 효율이 좋다.
생성자를 통해 데이터의 초기 크기를 지정할 수 없다.
출처: 이상민, <자바의 신 VOL.2> 로드북
'Java > 자바의 신 VOL.2' 카테고리의 다른 글
07. 쓰레드는 개발자라면 알아두는 것이 좋아요 (1) | 2024.07.03 |
---|---|
06. 자바랭 다음으로 많이 쓰는 애들은 컬렉션 - Part3(Map) (0) | 2024.06.28 |
04. 자바랭 다음으로 많이 쓰는 애들은 컬렉션 - Part1 (List) (0) | 2024.06.28 |
03. 실수를 방지하기 위한 제네릭이라는 것도 있어요. (0) | 2024.06.27 |
02. 가장 많이 쓰는 패키지는 자바랭 (0) | 2024.06.27 |