출처 : 열혈 java 프로그래밍
컬렉션 프레임워크란 ?
List<E>
인터페이스를 구현하는 컬렉션 클래스
ArrayList<E>
배열 기반LinkedList<E>
리스트 기반 List<E>
인터페이스를 구현하는 클래스의 특징
import java.util.*;
public class Main {
public static void main(String[] args){
//컬렉션 인스턴스 생성
List<String> list = new ArrayList<>();
//저장
list.add("hello");
list.add("bye");
//삭제
list.remove(0);
//참조
String s = list.get(0);
System.out.println(s);
}
}
기본적 기능들은 위와 같음
ArrayList는 내부적으로 배열을 생성함. 필요하면 배열의 길이를 스스로 늘림
List<Integer> list2 = new ArrayList<>(10);
성능에 신경을 써야 한다면 생성자의 인자로 미리 공간을 확보할 수 있음
LinkedList도 ArrayList와 같은 방법으로 사용한다.
LinkedList는 연결 리스트 자료구조를 사용한다.
따라서 저장 공간을 계속 추가할 수 있어 미리 할당할 필요는 없다.
ArrayList
장점
단점
LinkedList
장점
단점
컬렉션 클래스를 생성할 때 다른 컬렉션 인스턴스를 생성자로 받아서 생성할 수 있다.
= 다른 컬렉션 인스턴스에 저장된 데이터를 복사해서 새로운 컬렉션 인스턴스 생성가능
List<Integer> list = Arrays.asList(1,2,3,4,5);
//다른 컬렉션 인스턴스를 생성자로 받아서 생성
list = new ArrayList<>(list);
list.add(6);
for (Integer i : list){
System.out.println(i);
}
위 방식과 같이 ArrayList를 사용하다가 LinkedList가 필요하면 단순히 이렇게 해주면 된다.
list = new LinkedList<>(list);
Collection이 Iterable를 상속함
제네릭 클래스들은 Collection을 구현함
따라서 Iterator의 추상 메소드들을 구현함
import java.util.*;
public class Main {
public static void main(String[] args){
List<Integer> list = new ArrayList<>();
for (int i=1;i<=3;i++){
list.add(i);
}
//반복자
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()){ //next 메소드로 참조할 값이 있는지 확인
System.out.println(iterator.next()); //다음 인스턴스의 참조값 반환
iterator.remove(); //next 메소드 호출을 통해 반환했던 인스턴스 삭제
}
}
}
반복자는 생성과 동시에 첫번째 인스턴스를 가리킴. next가 호출될 때마다 뒤로 이동한다.
반복자를 다시 처음 위치로 되돌릴 수는 없다.
반복자를 다시 얻어야 처음 위치에서 재시작 할 수 있다.
연결 리스트만 양방향 반복자인 ListIterator를 사용할 수 있음
Iterator를 상속하는 클래스이고 양쪽 방향으로 이동 가능하다.
previous()
hasPrevious()
add, set
등을 추가로 호출할 수 있다.
Set<E>
인터페이스를 구현하는 제네릭 클래스의 특징
import java.util.*;
public class Main {
public static void main(String[] args){
Set<String> set = new HashSet<>();
set.add("Toy");
set.add("Joy");
set.add("Enjoy");
set.add("Happy");
set.add("Happy");
Iterator<String> it = set.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
저장순서가 유지되지 않고, 중복저장이 허용되지 않음을 확인할 수 있다.
중복저장이 허용되지 않는다 -> 같은 인스턴스로 판단하는 기준은 ?
Object 클래스에 정의된 두 메소드의 호출 결과를 근거로 판단한다
public boolean equals(Object obj)
public int hashCode()
자세한 내용은 책 568p 참고
먼저 hashCode 메소드의 반환값을 통해 분류된 위치 비교, 분류된 그룹 내에서 equals를 호출해서 동등 비교
hashCode와 equals를 오버라이딩해서 원하는 대로 비교하게 바꿀 수 있다.
특정 인스턴스에 대해 HashMap을 사용할 때마다 hashCode 메소드를 새로 정의하기는 번거롭다.
java.utils.Objects에서 제공하는
pulic static int hash(Object...values)
를 사용하면 쉽게 오버라이딩 할 수 있다.
가변 인자로 선언된 메소드로 메소드 호출 시마다 인자 수를 달리 할 수 있다. 하나 이상의 인자를 조합해 해쉬값을 만들어 반환하기 떄문에 특별한 경우가 아니면 이 메소드를 사용하면 된다.
TreeSet<E>
는 트리 자료구조를 기반으로 인스턴스를 저장한다.
트리 자료구조를 활용하기 때문에 정렬된 상태가 유지되면서 인스턴스가 저장된다.
import java.util.*;
public class Main {
public static void main(String[] args) {
Set<Integer> set = new TreeSet<>();
set.add(3);
set.add(4);
set.add(2);
set.add(1);
Iterator<Integer> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next()); // 1 2 3 4 오름차순 순서
}
}
}
Integer의 경우 오름차순이 기본이지만, 다른 클래스들의 경우 프로그래머가 정해줘야 한다.
public interface Comparable<T>
인터페이스의 추상 메소드
int compareTo(T o)
를 구현해야 한다.
정렬 기준은 Comparable
인터페이스의 compareTo
와 같다
TreeSet에서 사용할 객체가 Person 이라면 Comparable<Person>
을 구현하도록 하고 compareTo(Person p)
를 구현해주면 된다.
스택, 큐, 맵은
자바 코테용 함수
여기를 참고하자.
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
stack.push(1);
stack.peek();
stack.pop();
Queue<Integer> queue = new LinkedList<>();
queue.offer(1);
queue.peek();
queue.poll();
HashMap<Integer,Integer> map = new HashMap<>();
map.put(1,1);
map.put(2,2);
map.get(1);
map.values();
map.keySet();
map.entrySet();
}
Collections 클래스에는 다양한 알고리즘을 구현한 메소드가 존재한다.
public static <T extends Comparable<T>> void sort(List<T> list)
List<E>
를 구현한 컬렉션 클래스들을 정렬하는 데 사용하는 메소드이다.
List<T>
의 인스턴스는 모두 전달 가능 Comparable<T>
인터페이스를 구현한 상태여야 함 다음과 같이 사용한다
Collections.sort(list);
호출 시 정렬의 기준을 정할 수 있도록 정의된 메소드도 있다.
public static <T> void sort(List<T> list, Comparator<? super T> c)
import java.util.*;
public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(5,3,4,1,2,6));
Collections.sort(list,(a,b)->b-a);
Iterator<Integer> it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
사용 예시는 위와 같다.