8.1 컬렉션 팩토리
적은 요소 리스트 넣기
- List 만들어서 add 근데 새 문자열 저장하는데 많은 코드 필요
- Arrays.asList() 팩토리 메서드 사용 하면 줄일 수 있음
→ 고정 크기 리스트 요소 갱신 가능 , 새요소 추가 요소 삭제 불가
→ UnsupportedOperationException 예외 발생
8.1.1 리스트 팩토리
- List.of 팩토리 메소드를 이용하면 간단하게 리스트 만들 수 있음
- 요소 추가 불가능, 예외 발생
- 컬렉션이 의도치 않게 변하는 것을 막을 수 있음
- 요소 자체가 변하는 것을 막을 수 있는 방법은 없음
- Collectors.toList() 컬렉터로 스트림을 리스트로 변환 가능
- 데이터 처리 형식을 설정하거나 데이터를 변환할 필요가 없ㄷ아면 사용하기 간편한 팩토리 메서드를 이용할 것을 권장
8.1.2 집합 팩토리
Set friends = Set.of(”~);
8.1.3 맵 팩토리
- 키와 값이 필요
- Map.of 팩토리 메서드에 키와 값을 번갈아 제공하는 방법으로 맵을 만들 수 있음
Map<String,Integer> ageOfFriends = Map.of(”Raphael”,30,”Olivia”,25);
- 열개 이하의 키와 값 쌍을 가진 작읍 맵을 만들 때 유용
- 그 이상 Map.Entry<K,V> 객체를 인수로 받으며 가변 인수로 구현된 Map.ofEntries 팩토리 메서드를 이용하는 것이 좋음
8.2 리스트와 집합 처리
List,Set 인터페이스에 다음과 같은 메서드 추가
- removeIf
- replaceAll
- 리스트에서 이용할 수 있는 기능으로 UnaryOperator 함수를 이용해 요소를 바꿈
- sort
8.2.1 removeIf 메서드
- Iteraotr 객체, next(),hasNext()를 이용해 소스를 질의
- Collection 객체 자체, remove()를 호출해 요소를 삭제
반복자의 상태는 컬렉션의 상태와 서로 동기화 되지 않음
- Iterator 객체를 명시적으로 사용하고 그 객체의 remove() 메서드를 호출함으로써 문제 해결
removeIf 메서드는 삭제할 요소를 가리키는 프레디 케이를 인수로 받기 때문에 위를 바꾸면 단순하게 해결가능
→ 삭제가 아니라 바꿔야하는 상황이 있는데 이때는 replaceAll 제공
8.2.2 replaceAll 메서드
- List에 replaceAll 이용하며 리스트의 각 요소를 새로운 요소로 변경
- 일반적인 스트림
referenceCodes.stream()
.map(Strings::toUpperCase))
.collect(toList());
- 이렇게 사용하면 새로운 컬렉션이 생성되고 기존 컬렉션 변경 X
for (ListIterator<String> iterator = referenceCodes.listIterator(); iterator.hasNext();) {
iterator.hasNext();
String code = iterator.next();
iterator.set(code.toUpperCase());
}
- Iterator와 혼용하여 사용하면 문제 일으킴
referenceCodes.replaceAll(code -> code.toUpperCase());
이렇게 사용 가능
8.3 맵처리
8.3.1 forEach 메서드
맵에서 Key, Value을 반복하며 확인하려면 Map.Entry<K, V>의 반복자를 활용
ageOfFriends.forEach((friend, age) -> print(friend + "is" + age)))
8.3.2 정렬 메서드
- 아래 두개 맵의 항목을 값을 또는 키를 기준으로 정렬가능
- Entry.comparingByValue
- Entry.comparingByKey
8.3.3 getOrDefault 메서드
기존에는 존재하지 않는 키로 값을 찾으려할때 NPE가 발생할 가능성이 있어서 Null 체크가 필요
- computeIfAbsent : 제공된 키에 해당하는 값이 존재하지 않으면(값이 없거나 Null) 제공된 키로 새로운 Value를 맵에 추가
- computeIfPresent : 제공된 키가 존재하면 새로운 Value로 맵에 추가
- compute : 제공된 키로 새 Value를 추가
8.3.4 계산 패턴
맵에 키가 존재하는지 여부에 따라 어떤 동작을 실행하고 결과를 저장해야하는 상황이 필요한 때가 있음
8.3.5 삭제 패턴
remove(key, value);
8.3.6 교체 패턴
- 맵의 항목을 변경하는데 사용할 수 있는 두 개의 메서드가 추가
- replaceAll : BiFunction을 적용한 결과로 각 항목의 값을 교체 이전에 알려준 List.replaceAll과 비슷한 기능
- replace : 키가 존재하면 맵의 값을 바꿈 키가 특정 값으로 매핑되었을때만 변경하도록 하는 오버로드된 버전도 있음
8.4 개선된 ConcurrentHashMap
8.4.1 리듀스와 검색
- ConcurrentHashMap은 스트림에서 봤던것과 비슷한 종류의 세 가지 연산을 지원
- forEach : 각 (key, value) 쌍에 주어진 액션을 실행
- reduce : 모든 (key, value) 쌍을 제공된 리듀스 함수를 이용해 결과로 합침
- search : 널이 아닌 값을 반환할 때 까지 각 (key, value)쌍에 함수를 적용
- 다음처럼 키에 함수 받기, 값, Map.Entry, (key, value)인수를 이용한 네 가지 연산 형태를 지원
- 키 값으로 연산 (forEach, reduce, search)
- 키로 연산(forEachKey, reduceKeys, searchKeys)
- 값으로 연산(forEachValue, reduceValues, searchValues)
- Map.Entry 객체로 연산(forEachEntry, reduceEntries, searchEntries)
8.4.2 개수
- ConcurrentHashMap은 맵의 매핑 개수를 확인하는 mappingCount 메서드를 제공
8.4.3 집합뷰
- ConcurrentHashMap 클래스는 ConcurrentHashMap을 집합 뷰로 반환하는 keySet이라는 새 메서드를 제공
- 맵을 바꾸면 집합도 바뀌고 반대로 집합을 바꾸면 맵도 영향 받음