Clean Code that Works.

http://www.javacodegeeks.com/2013/02/40-java-collections-interview-questions-and-answers.html

저기 있는거 번역..
맨날 HashMap하고 ArrayList 만 쓰다 보면, 컬렉션 프레임워크가 뭔지 잊어 버릴때가...-_ -;;


======================================================================================================================

1. 자바 컬렉션 프레임워크는 무었이고, 이들을 사용하므로서 얻는 이득은 무엇인가?
  컬렉션은 대부분의 프로그래밍 언어에서 사용되고 있고 초창기 자바에서는 VectorStackHashtableArray만 제공되고 있었다. 자바 1, 2가 릴리즈 되면서 컬렉션 프레임워크들은 colletions 인터페이스를 구현하고 해당 알고리즘도 구현되었다. 자바 컬렉션들은 제너릭스의 활용과 Thread-safe한 기능들까지 제공하고 있다. 
컬렉션 프레임워크를 사용함으로써 얻을 수 있는 이점들을 아래와 같다.
  • 별도로 컬렉션 클래스를 구현하는 것보다 구현되있는것을 사용함으로써 코딩 시간을 감소 시킬 수 있다.
  • 컬렉션 프레임워크들은 잘 테스트 되고 검증되어있기때문에 코드 품질을 보장한다.
  • JDK에 포함된 컬렉션 프레임워크들을 사용하여 코드 유지보수 시간을 감소 시킬 수 있다.
  • 재사용 가능하고 상호 운용성이 보장 된다.

2. 컬렉션 프레임워크에 제너릭스가 도입되면서 생긴 장점은 무엇인가?
  자바 1.5 버전부터 제너릭스가 도입되었다. 제너릭스를 통해 컬렉션 관련 코드를 작성할때 해당 오브젝트의 타입을 지정할 수 있게되었고 이로 인해 잘못된 타입의 오브젝트를 세팅할 경우 컴파일 시점에서 이를 파악할 수 있게 되었다. 이로 인해 런타임시 발생하는 ClassCastException을 컴파일시 찾아 낼 수 있게 되었다. 그리고 제너릭스를 통해 클래스 캐스팅을 하지 않아도 되고 instansof 를 사용하지 않아도 되므로써 코드를 좀 더 깔끔하게 유지할 수 있게 되었다. 

3. 자바 컬렉션 프레임워크의 기본 인터페이스들은 무엇인가?
  • Collection 은 가장 기본이 되는 인터페이스이다. 자바는 이 인터페이스를 직접 구현한 클래스는 아무것도 제공하지 않는다.
  • Set 은 중복을 허용하지 않는 집합이다. 
  • List 는 중복을 허용하고 정렬이 가능한 컬렉션이다. 인덱스를 통해 아무런 엘리먼트나 접근할 수 있고, 길이 조정이 가능한 배열과 비슷하다고 할 수 있다.
  • Map 은 키/값을 가지고 있는 오브젝트다. 키값은 중복되어선 안되고 하나의 키 값은 하나의 값에 매핑된다.
다른 인터페이스들론 Queue, Deque, Iterator, SortedSet, SortedMap, ListIterator가 있다.

4. 왜 컬렉션은 Cloneable 과 Serializable 인터페이스를 상속받지 않았는가?
  컬렉션은 오브젝트들을 묶어서 관리하고 이를 어떻게 유지하는지는 관여하지 않는다. 예를들어 몇몇 컬렉션들은 중복 값을 허용하는 List를 사용하거나 중복 값을 허용하지 않는 Set같은것을 사용한다. 많은 컬렉션 구현체들이 clone 함수를 가지고 잇다. 하지만 이것이 모든 컬렉션이 전부다 clone 을 가지고 있어야 된다는 것을 의미 하지는 않는다. 컬력션은 추상 인터페이스고 실제 구현체에서 어떻게 사용해야 될지를 결정해야 된다.

5. 왜 Map 인터페이스는 컬렉션 인터페이스를 상속받지 않는가?
  Map 인터페이스와 이 구현체들은 컬렉션 프레임워크에 속하지만 Map은 컬렉션이 아니고 컬렉션 역시 Map이 아니다. 
만약 맵이 컬렉션 인터페이스를 상속 받았다고 치면 엘리먼트들은 어떻게 관리해야 될까? 맵은 키-값 을 가지고 있고 컬렉션 처럼 키와 값들을 검색하는 메서드들을 제공한다. 하지만 이 것은 "엘리먼트들의 그룹"이라는 컬렉션 인터페이스의 기본 개념과 맞지 않는다.

6. Iterator는 무엇인가?
  Iterator 인터페이스는 아무 컬렉션이든 반복적으로 수행하기 위한 메서드를 제공한다. iterator 메서드를 통해 컬렉션으로 부터 iterator instance를 가져올 수 있다. Iterator는 자바 컬렉션 프레임워크에서 Enumeration에 속한다. Iterator는 컬렉션을 순회하는 도중에 엘리먼트들을 삭제할 수 있다.

7. Enumeration 과 Iterator 인터페이스의 다른점은 무엇인가?
  Enumeration은 Iterator 보다 두배이상 빠르고 더 작은 메모리를 사용한다. Enumeration은 매우 간단하고 간단한 요구사항에 잘 동작되도록 최적화 되어 있다. 하지만 Iterator는 Enumeration에 비해 더 안전한데 그 이유는 Iterator가 사용될때 대상 컬렉션을 다른 쓰레드에서 접근해서 수정하는것을 막기 때문이다.
Iterator 는 자바 컬렉션 프레임워크의 Enumeration에 포함된다. iterator는 작업을 수행하면서 해당 엘리먼트를 삭제할 수 있지만 Enumeration은 불가능 하고 iterator의 메서드 이름은 기능적으로 명확하게 반복을 한다는 뜻으로 정의 되어있다.

8. 왜 다른 컬렉션 처럼 Iterator.add() 메서드는 없는가?
  이 말은 의미적으로 불명확 한데 iterator에 add를 추가 한다면 이는 반복작업의 순서를 보장하지 않는다. 하지만 ListIterator는 반복 작업을 할때 순서를 보장하기 때문에 add 기능을 제공한다.

9. 왜 Iterator는 Cursor 없이 직접적으로 이동할 수 있는 next 메서드를 제공하지 않는가?
  Iterator 인터페이스에 추가될 수는 있지만 많이 사용되지 않을 것이고, Iterator를 구현하는 클래스마다 이를 만들어 줘야 되기 때문에 제공되지 않는다. 그리고 Iterator(반복)이라는 의미와 맞지도 않는다.

10. Iterator 와 ListIterator의 차이점은 무엇인가?
  • Set과 List에 Iterator를 사용할 수 있지만 ListIterator에는 List만 가능하다.
  • Iterator 는 앞쪽으로 탐색을 하지만 ListITerator는 양방향 순회가 가능한다.
  • ListIterator는 Iterator 인터페이스를 상속받았고 추가적으로 Add, 엘리먼트 교체, 현제 index의 이전, 다음 엘리먼트 가져오기 등 많은 추가 기능을 제공한다.
11. List를 반복할 수 있는 방법은 무엇인가?
  Iterator를 사용하던가 for-each loop 를 사용하는 두가지 방법을 사용해서 List를 반복 할 수 있다.

01List<String> strList = new ArrayList<>();
02//using for-each loop
03for(String obj : strList){
04    System.out.println(obj);
05}
06//using iterator
07Iterator<String> it = strList.iterator();
08while(it.hasNext()){
09    String obj = it.next();
10    System.out.println(obj);
11}

 Iterator를 사용하는게 좀더 thread-safe한데 만약 반복 도중에 엘리먼트가 수정되려고 한다면 ConcurrentModificationException을 발생시킨다.

12. Iterator의 fail-fast에 대해 알고 있는것은 무엇인가?
  Iterator의 fail-fast 속성은 다음 엘리먼트에 접근 하려고 할 때 엘리먼트가 변한것이 있는지 확인하는 것이다. 만약 수정 사항이 발견된다면 ConcurrentModificationException를 발생시킨다. 모든 Iterator의 구현체는 ConcurrentHashMap이나 CopyOnWriteArrayList 동시성 관련된 컬렉션을 제외 하고 처럼 fail-fast를 사용하는 방법으로 디자인 되어 있다.

13. fail-fast 와 fail-safe 의 다른 점은 무엇인가?
  fail-fast를 사용하는 방식의 컬렉션들은 java.util 패키지에 들어가있고 fail-safe는 java.util.concurrent 패키지에 위치하도록 디자인되어 있다. Fail-fast Iterator는 ConcurrentModificationException 을 발생 시키고 fail-safe는 절대로 ConcurrentModificationException를 발생 시키지 않다. 

14. 컬렌션을 순회하는 도중에 ConcurrentModificationException이 발생하는것을 피할려면 어떻게 해야 되는가?
  concurrent 컬렉션을 사용하면 ConcurrentModificationException이 발생하는것을 예방 할 수 있다. ex) ArrayList 대신 CopyOnWriteArrayList를 사용

15. Iterator 인터페이스의 구현체가 없는 이유는 무엇인가?
  Iterator 인터페이스는 컬렉션들을 반복하는데 사용할 메서드들이 정의되어 있지만 실제 구현은 컬렉션의 구현체가 가지고 있다. 모든 컬렉션 클래스들은 순회를 하기 위해 내부에 Iterator를 구현한 코드를 가지고 있다. 이를 통해 iterator가 fail-fail을 사용할지 fail-safe를 사용할지 결정할 수 있도록 한다. ArrayList의 Iterator는 fail-fast이고 CopyOnWriteArrayList의 Iterator는 fail-safe이다.

16. UnsupportedOperationException 은 무엇인가?
  UnsupportedOperationException 은 사용할려는 메서드가 제공되지 않을 때 발생하는 오류이다. JDK 내에서도 넓게 사용되고 있으며 컬렉션 프레임워크에서는 모든 add 및 remove 메서드가 java.util.Collections.UnmodifiableCollection 를 던진다.

17. 자바에서 HashMap은 어떻게 동작하는가?
- HashMap 은 키-값 쌍으로 사용하도록 구현되어 있다. HashMap은 해싱 알고리즘을 사용하고 hashCode()와 equals()를 put() 과 get()을 쓸대 사용한다. 키-값 을 저장하기 위해 put 메서드를 호출 하면 HashMap은 key의 hashCode()를 호출해서 맵에 저장되어 있는 값 중에 동일한 key가 있는지 찾는다. 이 Entry는 LinkedList에 저장되어 있고 만약 존재하는 entry면 equals()메서드를 사용해서 key가 이미 존재 하는지 확인 하고 만약 존재 한다면 value값을 덮어 씌워서 새로운 키-값 으로 저장한다. 키를 가지고 get 메서드를 호출하면 hashCode()를 호출해서 array에서 값을 찾고 equals()메서드를 가지고 찾고자 하는 key와 동일한지 확인한다. 아래 이미지를 보면 명확하게 알 수있다.


HashMap에 대해 알아야할 다른 중요한 것은 capacity, load factor, threshold resizing이다. HashMap은 기본적으로 capacity 는 32, load factor는 0.75로 세팅하고 Threshold는 entry를 추가할 때 마다 capacity에 load factor를 곱한 값이 된다. 만약 map이 크기가 threshold 보다 크면 HashMap은 더 큰 capacity를 사용하도록 맵을 재 해시한다. capacity는 항상 
데이터베이스의 데이터를 캐싱하는 것 같은 많은 수의 key-value 쌍을 저장할때 알아야된다. 이것은 HashMap을 적절한 capacity 와 load factor를 사용해서 초기화 하는 좋은 방법이다.

18. hashCode()와 equals() 메서드의 중요점음 무엇인가?
  HashMap은 Key 오브젝트의 hashCode()와 eqauls()메서드를 사용해서 key-value 값을 저장할 위치를 결졍하고 HashMap에서 값을 꺼내올때도 사용한다. 만약 이 메서드들이 올바르게 구현되지 않았다면 다른 두개의 Key가 같은 hashCode() 및 eqauls() 결과를 내놓을 수 있고 이는 value 값들을 잘못된 의도하지 않은 값으로 덮어 씌울 가능성이 있다. 
equals()와 hashCode()의 구현은 아래 기본룰을 따라야 된다.
  • If o1.equals(o2), then o1.hashCode() == o2.hashCode()should always be true.
  • If o1.hashCode() == o2.hashCode is true, it doesn’t mean that o1.equals(o2) will be true.
19. 아무 클래스나 Map의 Key로 사용할 수 있는가?
 아무 클래스나 사용 가능 하지만 아래 몇몇 주의사항을 따라야 된다.
  • 만약 클래스가 equals()를 overrides 했다면 hashCode() 역시 override 해야 한다.
  • 18번에 언급된 기본 구현 규칙을 따라야 한다.
  • equals() 메서드가 사용되지 않으면 hashCode()도 사용하지 않아야 한다.
  • 가장 좋은 방법은 key 클래스를 불변(immutable)으로 만드것이다. 이렇게 하면 hashCode()값은 캐시되어 빠른 성능을 가진다. 또한 불변 클랙스는는 hashCode() 및 equals()의 값이 변하지 않기 때문에 해당 값이 변해서 생기는 문제들을 해결할 수 있다. 예를 들어 아래 HashMap의 key 로 사용될 MyKey 클래스를 살펴봐라.
01//MyKey name argument passed is used for equals() and hashCode()
02MyKey key = new MyKey('Pankaj'); //assume hashCode=1234
03myHashMap.put(key, 'Value');
04 
05// Below code will change the key hashCode() and equals()
06// but it's location is not changed.
07key.setName('Amit'); //assume new hashCode=7890
08 
09//below will return null, because HashMap will try to look for key
10//in the same index as it was stored but since key is mutated,
11//there will be no match and it will return null.
12

myHashMap.get(new MyKey('Pankaj'));


이런 이유로 인해 대부분 String 이나 Integer 값들을 HashMap의 키로 사용한다.

20. Map 인터페이스가 제공하는 다른 Collection 뷰는 무엇인가?
  Map 인터페이스는 아래 3가지 형태의 collection view 를 제공한다.
  • Set keySet(): 맵에 존재하는 Key 값들을 Set으로 보여준다. 이 set들은 맵과 연결되어 있으며 맵을 바꾸거나 set을 바꾸면 값이 수정 된다. 만약 키 Set을 사용하는중에 map이 변경 되면 Set을 반복할때 나오는 결과값은 undefined 되게 된다. Set은 엘리먼트들을 지울 수 있고 이에 대응하는 값은 맵에서 삭제 된다.(remove, Set.remove, removeAll, retaionAll, clear) add 나 addAll같은 기능은 제공하지 않는다.
  • Collection values() : 맵에 존재하는 Value 들을 컬렉션 형태로 보여준다. 이것 역시 맵과 연동되어 있으며 collection을 수정 하면 map의 값이 수정된다. 
  • Set<Map.Entry<K, V>> entrySet() : 맵의 entry 들을 Set 형태로 보여준다.
21. HashMap과 Hashtable의 차이점은 무엇인가?
  HashMap과 Hashtable은 둘다 Map 인터페이스를 구현하고 있어서 비슷해 보이지만 아래와 같은 차이점이 존재한다.
  • HashMap은 키/값에 null을 허용하는 반면 Hashtable은 이를 허용하지 않는다. 
  • Hashtable은 synchronized (synchronized) 되어 있지만 HashMap 은 그렇지 않다. 그래서 HashMap 은 단일 스레드 환경에서 더 좋은 퍼포먼스를 보여준다. 반면, Hashtable은 멀티 스레드 환경에 적합하다. 
  • LinkedHashMap 은 자바 1.4에서 HashMap의 서브클래스로 소개되었다. 그렇기 때문에 iteration 의 순서를 보장받고 싶다면,  HashMap에서 LinkedHashMap으로쉽게 변경 가능하다. 그러나 Hashtable 에서는 그럴 수 없으므로 iteration 순서를 예측할 수 없다.  
  • HashMap은 iterator 키 셋을 제공하므로 fail-fast (12 참고) 기능을 사용하나 Hashtable은 Enumeration 키를 사용하므로 이런 기능을 제공하지 못한다. 
  • Hashtable은 legacy 클래스로 취급을 받기 때문에 만약 Map에서 iteration을 하는 도중에 수정가능한 Map을 사용하고 싶다면 ConcurrentHashMap을 사용하면 된다. 
22. HashMap과 TreeMap중 무엇을 사용할지 어떻게 판단하는가?
  엘리먼트들을 추가, 삭제, 위치 변경등 작업을 하고 싶으면 HashMap이 최고의 선택이다. 하지만 만약 정렬되어 있는 key값에 따라 탐색을 하기 원한다면 TreeMap을 사용하는 것이 더 좋다. 컬렉션에 크기에 따라 다르지만 HashMap에 엘리먼트를 추가 하고 이를 TreeMap으로 변환하는게 키를 정렬해서 탐색하는 경우보다 더 빠르게 동작 한다.

23. ArrayList와 Vector간의 비슷한점과 차이점은 무엇인가?
  ArrayList와 Vector는 여러면에서 비슷하다
  • 인덱스 기반이고 내부적으로 배열로 백업 할 수 있다.
  • 엘리먼트들을 추가한 순서를 가지고 있고 이 순서를 가져 올 수도 있다.
  • iterator를 구현하였으므로 fail-fast 방식이다.
  • null 값을 가질 수 있고 인덱스 번호를 사용해 랜덤으로 접근 할 수 있다.

  아래는 ArrayList와 Vector의 차이점이다.
  • Vector는 synchronized 되어 있지만 ArrayList는 그렇지 않다. 만약 iterating 중에 엘리먼트를 수정 하고 싶다면 CopyOnWriteArrayList를 사용하면 된다.
  • ArrayList는 synchronized에 따른 간접비용이 아무것도 없기 때문에  Vector보다 빠르다. 
  • ArrayList가 좀 더 다재다능 한데 Collection Utility 클래스에서 제공하는 기능으로 synchronized를 시키거나 읽기 전용 리스트를 만들수도 있다.

24. Array와 ArrayList의 차이점은 무엇이고 언제 ArrayList를 사용해야 하는가?
  Array는  primivite 타입이나 Object 둘다 사용 가능 하지만 ArrayList는 Object만 사용 가능하다.
Array는 길이가 고정이 되있지만 ArrayList는 동적으로 변경 가능하다.
Array는 ArrayList처럼 다양한 기능을 제공하지 않는다.(addAll, removeAll, iterator 등등) 목록에 관련된 작업을 할때 ArrayList를 사용하는 것이 좋지만 가끔 Array를 사용하는것이 좋을 때가 있다
  • 리스트의 크기가 고정되어 있고 값을 저장하거나 탐색 용도로만 쓸 경우
  • primitive 타입일 경우 
  • 만약 다차원 배열을 사용할 경우 [][] 배열을 사용하는게 List<List<>>를 쓰는것보다 쉽다.

25. ArrayList와 LinkedList의 차이점은 무엇인가?
  둘다 List 인터페이스를 구현하지만 약간 다른 점이 있다.
  •  ArrayList는 인덱스 기반의 Array로 구성되어 있어서 랜덤 엑세스를 할 경우 O(1)의 속도를 가진다. LinkedList는 데이터들이 이전, 다음 노드 처럼 서로 연결된 node로 구성되어 있다. 인덱스 번호를 사용해서 엘리먼트에 접근 하더라도 내부적으로는 노드들을 순차적으로 순회하며 엘리먼트를 찾는다. LinkedList 의 속도는 O(n)으로 ArrayList 보다 느리다.
  •  엘리먼트의 추가 및 삭제는 LinkedList가 ArrayList보다 빠른데 엘리먼트를 추가 및 삭제하는 중에 array를 리사이즈 하거나 인덱스를 업데이트를 할 일이 없기 때문이다.
  •  LinkedList의 엘리먼트들은 이전, 다음 엘리먼트들에 대한 정보를 가지고 있기 때문에 LinkedList가 ArrayList보다 더 많은 메모리를 소비한다.
 
 26. 랜덤 액세스를 제공하는 컬렉션은 무엇인가?
   ArrayList, HashMap, TreeMap, Hashtable 이 자신의 엘리먼트에 대한 랜덤 엑세스를 제공한다. 

  

27. EnumSet은 무엇인가?
  java.util.EnumSet은 Enum 타입을 활용해서 Set을 구현한 클래스다. Set이 생성 될 때 Set 안의 모든 엘리먼트들은 하나의 enum 타입을 구현한 것이어야 한다. EnumSet은 synchronized되어있지 않고 null 엘리먼트도 허용하지 않는다. copyOf, of, complementOf 같은 유용한 메서드를 제공한다. 아래 포스트를 참조보길 바란다.
  
28. thread-safe 한 컬렉션 클래스들은 무엇이 있는가?
  Vector, Hashtable, Properties, stack 은 synchronized 되어있는 클래스로 thread-safe 기 때문에 multi-thread 환경에서도 정삭적으로 동작한다. Java 1.5의 Concurrent AP에 포함되어 있는 몇몇 컬렉션 클랙스들은 반본 작업을 수행하는 도중에 컬렉션을 수정할수 있는데 이는 컬렉션의 복사본을 통해 작업을 하고 있기 때문이고 이들 역시 multi-thread 환경에서 안전한다.
  
29. Concurrent 컬렉션 클래스는 무엇인가?
  Java 1.5 Concurrent 패키지는 thread-safe 하고 ireating 작업 중에 컬렉션을 수정할 수 있는 클래스들을 포함하고 있다. Iterator는 fail-fast 하도록 디자인되어있고, ConcurrentModificationException을 발생 시킨다. 가장 잘 알려진 클래스로는 CopyOnWriteArrayListConcurrentHashMapCopyOnWriteArraySet이 있다. 
이 클래스들에 대해서는 아래 포스트를 참조 하길 바란다.
30. BlockingQueue는 무엇인가?
  java.util.concurrent.BlockingQueue는 엘리먼트들을 검색하거나 삭제 할때 대기하고, 큐에 엘리먼트가 추가 될 때 저장공간이 충분해 질때까지 기다리는 기능을 제공하는 Queue 이다. BlockingQueue는 자바 컬렉션 프레임워크에서 제공하는 인터페이스중에 하나로 주로 producer-consumer 문제에 주로 사용된다. BlockingQueue를 사용하면 producser가 cosumer에게 Object를 전달할때 저장공간 부족에 따르는 여러 문제점을 걱정할 필요가 없다. Java에서는 BlockingQueue를 구현한 ArrayBlockingQueue, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue등을 지원 한다.
  producer-consumer 문제에 BlockingQueue를 사용한 예제는 이 포스트를 참고 하라.
  
31. Queue, Stack 간의 차이점은 무엇인가?
  Queue와 Stack은 작업을 진행하기 전에 데이터를 저장하는데 사용된다. java.util.Queue
Queue는 엘리먼트들에 접근할때 First-In-First-Out(FIFO)를 사용하지만 항상 그러는 것은 아니다. Deque 인터페이스를 사용해서 양쪽 끝에서 엘리먼트에 접근할 수 있다. 
Stack은 queue와 비슷하지만 엘리먼트를 검색할때 Last-In-First-Out(LIFO)방식을 사용한다. 
Stack은 Vector 클래스를 확장해서 사용하지만 Queue는 인터페이스일 뿐이다.

32. Collections 클래스는 무었인가?
  java.util.Collections 는 유틸리티 클래스로 static 메서드로 구성되어 있고 컬렉션들을 조작하는데 사용된다. 다형성을 활용한 알고리즘들을 가지고 컬렉션을 조작하고 정의된 컬렉션의 형태로 새로운 컬렉션을 반환하고 다른 몇가지 기능들도 지원한다. 이 클래스는 컬렉션 프레임워크의 알고리즘(이진 검색, 정렬, 섞기, 뒤집기등)을  포함하고 있다.
  
33. Comparable 인터페이와 Comparator 인터페이스는 무엇인가?
  Java는 Arrays 와 Collections에 사용되는 정렬 메서드를 사용하기 위해 Comparable 인터페이스를 제공한다. 이 인터페이스는 compareTo 메서드를 가지고 정렬을 하는데 사용한다. 이 메서드를 구현할때 리턴값으로 음수, 0, 양수를 통해 엘리먼트들을 정렬하는데 사용하는데, 만약 비교하는 오브젝트가 적거나, 똑같거나, 크거나 하는 경우에 따라 리턴한다. 
그렇지만 실제 환경에서 사용할 경우에는 서로 다른 파라미터를 가지고 정렬을 하는 경우가 있을 것이다. 예를들어 CEO의 경우 연봉에 따라 사원들을 정렬하고 싶을수도 있고 HR에서 사원들의 나이를 가지고 정렬을 할 경우가 있다. 바로 이런 상황에서 Comparator 인터페이스를 사용하면 되는데 Comparable.compareTo(Object o)는 하나의 필드만 가지고 정렬을 수행하기 때문에 정렬에 필요한 오브젝트들 선텍할 수 있다. Comparator 인터페이스는 두개의 파라미터를 가지고 있는 compare(Object o1, Object o2) 메서드를 제공하는데 이 메서드는 만약 첫번째 변수가 두번째 변수보다 작으면 음수를 리턴하고 만약 두 값이 같으면 0, 더 크면 양수를 리턴한다.

Comparable 및 Comparator 인터페이스에 대해서 더 알고 싶으면 이 포스트를 참고 하라.

34. Comparable 인터페이스과 Comparator 인터페이스의 차이점은 무엇인가?
  Comparable 및 Comparator 인터페이스는 collection 및 Array 오브젝트들을 정렬 하는데 사용한다. Comparable 인터페이스는 오브젝트를 사용하여 정렬하는 방식을 제공하고 간단한 방식으로 제공된다. 
  Comparator 인터페이스는 정렬을 위한 다른 알고리즘을 제공하는데 정렬을 할 오브젝트들 중에서 특정 값을 선택하여  정렬하는데 사용할 수 있다.
  
35. Object들의 목록을 정렬시키려면 어떻게 해야 되는가?
  Object들의 배열을 정렬해야 될때는 Arrays.sort()를 사용하면 된다. 만약 오브젝트 목록들을 정렬시키고 싶으면 Collections.sort()를 사용하면 된다. 이 두 클래스는 sort() 메서드를 오버라이드 하고 있고 Comparable을 사용한 정렬 이나 Comparator를 사용한 정렬을 사용할 수 있다. Collections는 내부적으로 Arrays 의 sorting 메서드를 사용하고 있고, list를 array로 변환하는 경우를 제외하고 동일한 성능을 보여준다.
  
36. 만약 Collections를 함수에 파라미터로 전달할 경우, 이를 수정하지 못하게 할려면 어떻게 해야 되는가?
  함수로 파라미터를 전달하기 전에 Collections.unmodifiableCollection(Collection c) 메서드를 사용해서 읽기전용 커렉션을 생성할 수 있고 만약 컬렉션을 수정할려는 시도가 생기면 UnsupportedOperationException을 발생 시킨다.
  
37. 기존 컬렉션을 가지고 동기화된 컬렉션을 만들려면 어떻게 해야 되는가?
  Collections.synchronizedCollection(Collection c)를 사용해서 동기화된(thread-safe)한 컬렉션을 만들 수 있다.
  
38. 컬렉션 프레임워크내부에서 구현된 일반 알고리즘들은 무엇인가?
  컬렉션 프레임워크들을 일반적으로 알려진 정렬 및 검색 알고리즘에 대한 구현을 제공하고 Collections 클래스들은 이 메서드들을 가지고 있다. 대부분의 알고리즘음 List에서 주로 사용되지만 모든 컬렉션에도 사용할 수 있다.(정렬, 검색, 섞기, 최소-최대 값 찾기)

39. Big-O 표기법은 무엇인가? 예를 들어 줄 수 있는가?
  Big-O 표기법은 데이터 구조에 포함된 엘리먼트들의 숫자에 따라 알로리즘의 성능을 설명해주는 표기법이다. Collection 클래는 사실 데이터 구조이기 때문에 어떤 컬렉션을 사용할지 고려할때 시간, 메모리, 성능에 대한 Big-O 표기법을 기준으로 선택할때가 많다.
  • 예1 : ArrayList get(index i)는 엘리먼트의 숫자에 영향을 받지 않고 동일한 성능을 보여주기 때문에 Big-O 표기법으료 표시하면 O(1)으로 표기 할 수잇다.
  • 예2 : 배열이나 리스트에 대한 선형 탐색은 엘리먼트를 찾는데 엘리먼트들의 숫자에 영향을 받기 때문에 O(n)으로 표시한다.

40. Java 컬렉션 프레임워크의 모범사례는 무엇인가?
  • 필요에 따라 상황에 맞는 컬렉션을 선택해야 된다. 예를 들어 사이즈가 고정되어 있으면 ArrayList보다 Array를 사용할 수 있다. 만약 맵에 삽입된 순서되로 iterate를 하고 싶으면 TreeMap을 사용하는것이 좋다. 중복을 허용하고 싶으 않으면 Set을 사용하면 된다.
  • 몇몇 컬렉션 클래스들을 초기 용량을 지정할 수 있다. 만약 저장할 엘리먼트들의 사이즈를 알 경우에 초기 용량을 지정함으로써 rehashing이나 resizing이 일어나는것을 회피할 수 있다.
  • 코드를 작성할때 구현 클래스가 아닌 인터페이스를 기반으로 작성해야 나중에 구현체를 변경할때 코드를 재작성하는 수고를 줄일수 있다. 
  • 런타임에 발생할 수 있는 ClassCastException을 회피할려면 항상 제너릭스를 사용해서 type-safety 한 상태를 유지하라
  • 맵에 키를 사용할때 JDK에서 재공하는 immutable 클래스를 사용하여 사용자 클래스에서 hashCode()와 equals() 구현할 필요가 없게 하라
  • 읽기전용 및 동기화, 빈 컬렉션등을 만들때는 자신만의 구현으로 생성하지 말고 Collections에서 제공하는 유틸리티 클래스를 사용하라. 이는 코드 재사용성을 높여주고 안정적이며 유지보수 비용을 줄여 준다.