[모던 자바 인 액션]Chapter 8 컬렉션 API 개선

OhJuYeong·2025년 12월 29일

모던 자바 인 액션

목록 보기
7/9
post-thumbnail

8.1 컬렉션 팩토리

적은 요소 리스트 넣기

  • List 만들어서 add 근데 새 문자열 저장하는데 많은 코드 필요
  • Arrays.asList() 팩토리 메서드 사용 하면 줄일 수 있음

→ 고정 크기 리스트 요소 갱신 가능 , 새요소 추가 요소 삭제 불가

→ UnsupportedOperationException 예외 발생

  • HashSet 사용 가능

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이라는 새 메서드를 제공
  • 맵을 바꾸면 집합도 바뀌고 반대로 집합을 바꾸면 맵도 영향 받음
profile
기록하는 개발자

0개의 댓글