원본 본문으로 이동하기

자바 Collection : 1. List

박용서 - 자바 Collection 시리즈 1. List - https://gs.saro.me/#!m=elec&jn=802 2. Set, Map - https://gs.saro.me/#!m=elec&jn=803 머리 속으로 알고있는 것 보다 문서를 작성해보는 것이 어떨까 생각하여 강의를 작성해 보았습니다. 사실.. 기초강의일 뿐이고, 다 알고 있었다고 생각했는데... 강의를 쓰면서 확실치 않은 부분이 좀 있었습니다. 문서를 봐도 애매한건 JDK 소스 보면서 썼습니다. (다만, 문서에 나오지 않는 내용은 보증되지 않기 때문에, 참고용으로만 봤습니다.) 원시배열 원시배열은 이번 주제와 거리가 있지만 간단하게 설명하고 넘어갑니다. - 필자는 리스트와 햇갈리는 걸 방지하기 위해 원시배열이라는 용어를 사용하였습니다. https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html - 리스트가 아닌 원시적 형태의 배열!! (리스트가 아닙니다.) - 고정길이로 선언하며 한번 선언한 크기를 변경할 수 없습니다. - java.util.Arrays 에서 각종 유틸들을 지원합니다. - Array계열리스트(연접리스트)등은 내부적으로 이 원시배열을 가지고 있다가 필요할때 재할당을 합니다. // 선언 String[] array = new String; // 배열 -> 리스트 List<String> list = Arrays.asList(array); // 리스트 -> 배열 String[] array2 = list.toArray(new String[list.size()]); Vector : 연접리스트, thread-safe public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable https://docs.oracle.com/javase/8/docs/api/java/util/Vector.html - 자바의 초창기 1.0 버전부터 있던 원년맴버?? 입니다. - 연접 리스트인 동시에 쓰레드에 안전합니다. - 하지만 쓰레드 세이프가 필요없는 경우 약간의 자원이 낭비됩니다. List : 인터페이스 Interface List<E> extends Collection<E> https://docs.oracle.com/javase/8/docs/api/java/util/List.html - 위에서 볼 수 있듯 인터페이스 입니다. - Collection을 상속하고 있고, 때문에 Arrays 아닌 java.util.Collections 을 통해 유틸이 제공됩니다. https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html - 또한 원시배열과 다르게 동적 증감이 가능합니다. - 연접리스트들은 대부분(필자가 전체를 확인해보지 못했지만 봤을때 전부) capacity 설정을 통해 동적 생성의 단위를 지정해 줄 수 있습니다. ArrayList : 연접리스트 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html - 백터와 유사하지만 (둘다 내부적으로 원시배열을 가지고있음) 쓰레드에 안전하지 않습니다. - 쓰레드 안전 처리가 없기 때문에 Vector 보다 속도가 빠릅니다. - 일반적으로 동적으로 할당되며, 쓰레드에 안전할 필요가 없을 때 주로 쓰입니다. LinkedList : 연결리스트 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable https://docs.oracle.com/javase/8/docs/api/java/util/LinkedList.html - 내부적으로 Node 라는 클래스를 통해 머리와 꼬리를 연결시켜 연결리스트로 구현되어 있습니다. Queue, Deque : 인터페이스 public interface Queue<E> extends Collection<E> https://docs.oracle.com/javase/8/docs/api/java/util/Queue.html public interface Deque<E> extends Queue<E> https://docs.oracle.com/javase/8/docs/api/java/util/Deque.html - poll 계열의 메서드를 사용할 경우 삭제 후 반환 - peek 계열의 메서드를 사용할 경우 그대로 반환합니다. 연접리스트로 사용 예제 // ArrayDeque 는 Queue 정확히는 Deque를 상속받아 구현되어있다. // 이런식으로 사용할 경우 구현체 ArrayDeque 에 따라 연접리스트로 활용가능. // 짐작하겠지만 연접리스트로 큐/데큐를 구현하는것은 효율적인 방법이 아니다. Queue<String> que = new ArrayDeque<>(); Deque<String> deq = new ArrayDeque<>(); 연결리스트로 사용 예제 // 마찬가지로 LinkedList의 경우 Queue(Deque)를 상속받아 구현되어있다. // 연결리스트 형태로 사용할 수 있다. Queue<String> que = new LinkedList<>(); Deque<String> deq = new ArrayDeque<>(); BlockingQueue, BlockingDeque : 인터페이스, 블로킹, thread-safe public interface BlockingQueue<E> extends Queue<E> https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingQueue.html public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/BlockingDeque.html - 쓰레드에서 안전한 큐/데큐입니다. - 연접 리스트는 Deque를 지원하지 않습니다. - 필자도 정확한 이유가 적혀있는 공식문서는 찾지 못했지만, 연접리스트가 가변적으로 할당과 해제가 될때 큐/데큐는 비효율적이라서 인 것 같습니다. - 당장 ArrayBlockingQueue 의 소스를 보더라도 내부적으로 순환큐를 구현해놓고 부족할대 재할당을 하고있습니다. 연접리스트로 사용 예제 BlockingQueue<String> que = new ArrayBlockingQueue<>(기본크기); 연결리스트로 사용 예제 BlockingQueue<String> que = new LinkedBlockingQueue<>(); BlockingDeque<String> deq = new LinkedBlockingDeque<>(); ConcurrentLinkedQueue, ConcurrentLinkedDeque : 연결리스트, thread-safe public class ConcurrentLinkedQueue<E> extends AbstractQueue<E> implements Queue<E>, Serializable https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html public class ConcurrentLinkedDeque<E> extends AbstractCollection<E> implements Deque<E>, Serializable https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentLinkedDeque.html - 블록킹없는 쓰레드세이프 큐/데큐입니다. - 사실 필자는 쓰레드 세이프가 필요한 큐/데큐를 만들때 이걸 이용합니다. (블로킹은 써보지 않음) 사용 예제 Queue<String> que = new ConcurrentLinkedQueue<>(); Deque<String> deq = new ConcurrentLinkedDeque<>(); - 자바