collection 인터페이스는 기본자료형(int, long, char, boolean)이 아닌 참조자료형(Integer, String)을 쉽게 다룰 수 있게 해준다.
collection 인터페이스 및 구현체는 그 종류가 굉장히 다양한데, 크게 Collection인터페이스와 Map인터페이스로 나뉜다.
Collection은 한가지 데이터만을 위해 만들어졌고 Map은 두 데이터를 짝지어 다루기 위해 존재한다.

위 그림은 collection 프레임워크의 인터페이스 및 구현체의 구조도이다.
이 중 나는 오직 ps만을 위해 꼭 필요한 구현체만 골라서 쓸 예정이다.
ArrayList는 List인터페이스의 구현체로 일반 배열의 시간복잡도를 갖는다고 생각하면 된다.
public class Main{
public static void main(String[] args){
List<Integer> li = new ArrayList<>();
li.add(10);//add 맨뒤에 추가
li.add(1,20);//add(i,x) i번째에 x추가
li.get(0);//get(i) i번째 값 조회
li.set(0,100);//set(i,x) i번째 값 x로 변경
li.remove(0);//remove(i) i번쨰 값 삭제 단, 뒤에 값들 인덱스 땡겨짐
int n = li.size();//크기
if(li.isEmpty()){}//비어있는지 확인
if(li.contains(10)){}//포함여부
li.clear();//전체 삭제
li.sort(null);//오름차순 정렬
li.sort(Collections.reserveOrder());//내림차순 정렬
for(int i : li){//순회 1
System.out.println(i);
}
for(int i=0; i<li.size();i++){//순회 2
System.out.println(li.get(i));
}
}
}
ArrayDeque는 Queue인터페이스와 Deque인터페이스의 구현체로 사실 덱이라는게 큐랑 별다를게 없고, 앞부분에서 넣고 뒤에서 빼는게 queue라면 뒤에서도 넣고 앞에서도 뺄 수 있는, stack과 queue를 합쳐놓은게 deque이기 때문에 stack,queue,deque가 문제에서 필요할 때 사용한다.
public class Main{
public static void main(String[] args){
Queue<Integer> q = new ArrayDeque<>();
q.offer(10);//enqueue
int x = q.poll();//dequeue 꺼내서 없애기
int x = q.peek();//마지막꺼 꺼내서 보기만
if(q.isEmpty()){}//비어있는지 확인
int n = q.size();//크기
Deque<Integer> dq = new ArrayDeque<>();
dq.offerFirst(20);//앞에 넣기
dq.offerLast(20);//뒤에 넣기
int x = dq.pollFirst();//앞에 꺼내서 없애기
int x = dq.pollLast();//뒤에 꺼내서 없애기
int x = dq.peekFirst();//앞에 꺼내서 보기만
int x = dq.peekLast();//뒤에서 꺼내서 보기만
}
}
파이썬의 딕셔너리.
public class Main{
public static void main(String[] args){
Map<String,Integer> map = new HashMap<>();
map.put("apple",2);//넣기 단, 순서 없음
int x = map.get("apple");//apple이 키값임 즉 <key,value>임
int x = map.getOrDefault("banana",0);//get이랑 같은데, 키없으면 뒤에 default값 뱉음.
//get은 키가 없는 값이었다면 null을 뱉어서 NullPointException 일으킴
if(map.containKey("banana")){//키 존재 여부 체크
int x = map.get("banana");
}
map.remove("apple");//제거
map.clear();
int n = map.size();
if(map.isEmpty()){}
for(String k : map.keySet()){//HashMap은 순회할 때 foreach구문 사용 즉,':'사용
System.out.println(k);
}
for(int val : map.values()){//키는 keySet, 값은 values메소드
System.out.println(val);
}
for(Map.Entry<String, Integer> entry : map.entrySet()){
System.out.print(entry.getKey()+" "+entry.getValue());//키하고 값하고 같이 순회하려면 Map.Entry써야함
}
String st="avsa";
Map<Character, Integer> map = new HashMap<>();
for(char c : st.toCharArray()){
map.put(c,map.getOrDefault(c,0)+1);
}
}
}
집합 자료형 Set
public class Main{
public static void main(String[] args){
Set<Integer> set = new HashSet<>();
set.add(1);
set.remove(1);
if(set.contains(1)){}
int x = set.size();
if(set.isEmpty()){}
set.clear();
for(int i:set){
System.out.println(i);
}
}
}
우선순위 큐 (힙)
단, 기본적으로 최소힙이며 객체를 힙에 넣는 경우 멤버변수가 여러 개일 수 있어서 어느 기준으로 할지 람다를 <>()안에 넣던가 혹은 객체를 Comparable 인터페이스 구현체로 만들어야함
Comparable 사용
class Student implements Comparable<Student> {
String name;
int score;
Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int compareTo(Student other) {
return Integer.compare(this.score, other.score); // 오름차순
}
}
public class Main{
public static void main(String[] args){
Queue<Integer> heap = new PriorityQueue<>(Collections.reverseOrder());//점수로 내림차순 즉 최대힙, 최소힙으로 하려면 그냥 <>();
//메소드는 위에 설명한 Queue구현체인 ArrayDeque의 것과 동일
heap.offer(new Student("Kim", 80));
heap.offer(new Student("Lee", 95));
heap.offer(new Student("Park", 70));
while (!heap.isEmpty()) {
Student s = heap.poll();
System.out.println(s.name + " " + s.score);
}
}
람다식 사용
class Student{
String name;
int score;
Student(String name, int score) {
this.name = name;
this.score = score;
}
}
public class Main{
public static void main(String[] args){
Queue<Integer> heap = new PriorityQueue<>(
(a,b) -> Integer.compare(b.score, a.score)
);//점수로 내림차순 오름차순하려면 Integer.compare(a.score, b.score)
heap.offer(new Student("Kim", 80));
heap.offer(new Student("Lee", 95));
heap.offer(new Student("Park", 70));
while (!heap.isEmpty()) {
Student s = heap.poll();
System.out.println(s.name + " " + s.score);
}
}
자료형별 람다식 예시
Integer.compare(a,b);//정수인 경우
Character.compare(a,b);//char인 경우
Long.compare(a,b);//long인 경우
s1.compareTo(s2);//문자열인 경우
(a,b)->{
return Integer.compare(a,b);
}
(a,b)->{
return Character.compare(a,b);
}
(a,b)->{
long abs1 = Math.abs(a);
long abs2 = Math.abs(b);
int x = Long.compare(abs1,abs2);
if (x==0){return a>b?1:-1;}
return x
}
(a,b)->{
return s1.compareTo(s2);
}
문제를 풀다보면
public class Main{
public static void main(String[] args){
List<Integer> list = new ArrayList<>(List.of(1, 2, 3));
Set<Integer> set = new HashSet<>(List.of(1, 2, 3));
Deque<Integer> dq = new ArrayDeque<>(List.of(1, 2, 3));
PriorityQueue<Integer> pq = new PriorityQueue<>(List.of(3, 1, 2));
Map<String, Integer> map = new HashMap<>(Map.of("a", 1, "b", 2));
PriorityQueue<String> pq = new PriorityQueue<>(
(a, b) -> a.length() - b.length()
);//우선순위 먼저 정하려면 addAll로 객체 생성 이후에 추가
pq.addAll(List.of("aa", "bbbb", "c"));
}
}
}
배열, 큐, 덱, 스택, 집합, 딕셔너리(해시맵), 우선순위 큐(힙)
이상 ps할 때 쓰는 어지간한 자료구조를 collection Framework로 구현하는 법을 알아보았다.