The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future
fail-fast
위의 내용에 따르면 iterator로 컬렉션을 수정하는 동안 다른 스레드에서 동시에 Collection 요소를 수정할 경우, 즉시 예외를 발생시킨다는 것
이로 인해 다른 스레드에서의 예기지 않은 값의 변경을 막는다.
public class FailFastExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("orange");
Iterator<String> iterator = list.iterator();
Thread otherThread = new Thread(() -> {
try {
Thread.sleep(1000);
list.add("melon");
} catch (InterruptedException e) {
e.printStackTrace();
}
});
otherThread.start();
while(iterator.hasNext()) {
try {
Thread.sleep(1000); // Introduce a small delay
System.out.println(iterator.next());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Exception in thread "main" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1043)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:997)
at FailFastExample.main(FailFastExample.java:27)
위의 예시를 보면 thread sleep을 걸어 main쓰레드의 작업을 지연시키면서 list의 요소를 추가했다. fast-fail 원칙에 따라 ConcurrentModificationException 발생하는것을 확인할 수 있다. 위의 예제는 고의로 thread sleep을 주었지만, 다른 스레드에서 list작업 시 주의해야해야겠다.
List인터페이스를 구현한 클래스
Last In First Out 순으로 요소를 처리한다.
ArrayDequeu가 후입선출 성능은 빠르지만 쓰레드에 안전하지않으므로, 쓰레드에 안전하게 사용할려면 Stack클래스를 쓰는것이 좋다.
Deque<Integer> stack = new ArrayDeque<Integer>();


순서 상관없이, 중복 없이 데이터를 저장하는 컬렉션
→ 중복없이 원하는 값이 들어있는지 확인할때 사용
Set은 아래 세개의 구현체가 있다.
| 생성자 | 설명 |
|---|---|
| HashSet(int intialCapacity) | 매개변수로 받은 개수만큼의 데이터 저장공간과 0.75의 로드 팩터를 갖는 객체를 생성 |
| HashSet(int intialCapacity, float loadFactor) | 첫번째 매개변수로 받은 데이터 저장공간과 두 번째 매개변수로 받은 만큼의 로드 팩터를 갖는 객체를 생성 |
데이터의 개수 / 저장공간을 뜻한다.
데이터의 개수가 증가하여 로드팩터보다 커지면, 저장공간의 크기는 증가되고 해시 재정리 작업을 해야한다.
데이터가 해시 재정리 작업에 들어가면, 내부에 갖고 있는 자료구조를 다시 생성하는 단계를 거쳐야한다.
로드팩터라는 값이 클수록 데이터를 담을 공간의 넓어 지지만, 데이터를 찾는 시간은 증가한다.
그리하여 초기 공간 개수와 로드팩터는 데이터의 크기를 고려하여 산정하는것이 좋다.

LinkedList는 List, Dequeue, Queue 인터페이스를 구현하고 있다. 즉, LinkedList 자체가 List이면서 Queue, Dequeue인 셈이다.
Dequeue는 Double Ended Qeueu로 컬렉션의 요소를 맨 앞에서 값을 넣거나 빼는 작업, 맨 뒤에서 값을 넣거나 빼는 작업 시 용이하다.
LinkedList는 일반적인 배열타입의 클래스와 다르게 데이터들이 앞뒤로 연결되는 구조이므로 생성자로 객체를 생성할 때 처음부터 크기를 지정하지 않는다.