티스토리 뷰

Java

[Java] Map 디폴트 메소드

snail voyager 2023. 9. 10. 17:53
728x90
반응형

forEach 메서드

Map.Entry<K, V> 의 반복자를 이용하던 것을 BiConsumer를 인수로 받는 forEach 메서드 지원

Map<String, Integer> ageOfFriends = Map.of("A", 27, "B", 21, "C", 25);

for(Map.Entry<String, Integer> entry : ageOfFriends.entrySet()) {
    String friend = entry.getKey();
    Integer age = entry.getValue();
    System.out.println(friend + " is " + age + " years old.");
}

ageOfFriends.forEach((friend, age) -> System.out.println(friend + " is " + age + " years old."));

정렬 메서드

  • Comparator 객체를 반환하므로, 스트림 연산 중 sorted() 함수의 인자로 사용
  • Entry.comparingByKey : Comparator는 키를 기준으로 엔트리를 비교
  • Entry.comparingByValue : 값을 기준으로 엔트리를 비교
ageOfFriends
        .entrySet()
        .stream()
        .sorted(Map.Entry.comparingByValue())		//값을 기준으로 오름차순
        .forEachOrdered(System.out::println);
        
ageOfFriends
        .entrySet()
        .stream()
        .sorted(Map.Entry.<String, Integer>comparingByKey().reversed()) //키를 기준으로 내림차순
        .forEachOrdered(System.out::println);

getOrDefault 메서드

찾으려는 키가 없으면 null이 반환되어 NPE 발생

첫 번째 인수로 키, 두 번째 인수로 기본값

System.out.println(ageOfFriends.getOrDefault("D", 0));

계산 패턴

  • computeIfAbsent : 제공된 키에 해당하는 값이 없으면 키를 이용해 새 값을 계산하고 Map에 추가
    키가 존재하면 기존 값을 반환
  • computeIfPresent : 제공된 키가 존재하면 새 값을 계산하고 Map에 추가
  • compute : 제공된 키로 새 값을 계산하고 Map에 저장
Map<String, Integer> map = new HashMap<>();
int value = map.computeIfAbsent("A", key -> 1); //키가 없으면 새로운 값으로 추가
System.out.println(value);
System.out.println(map.computeIfAbsent("A", key -> 2)); //키가 존재하면 기존 값 반환

System.out.println(map.computeIfPresent("A", (k, v) -> 3)); //키가 존재하면 새로운 값으로 추가
System.out.println(map.computeIfPresent("B", (k, v) -> 4)); //키가 null이 아닐 때만 새로운 값 계산
System.out.println(map);	//{A=3}

System.out.println(map.compute("C", (k, v) -> 5));  //제공된 키로 새로운 값 계산하여 추가
System.out.println(map);	//{A=3, C=5}
System.out.println(map.compute("C", (k, v) -> 7));
System.out.println(map);	//{A=3, C=7}

compute()

compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

 

  • 주어진 키 key에 대해 remappingFunction을 실행하고, 반환된 값을 해당 키의 새로운 값으로 설정합니다.
  • 만약 remappingFunction의 반환값이 null이면 해당 키가 맵에서 제거됩니다.
  • 기존 값이 없는 경우, null을 값으로 넣어 함수가 실행됩니다.
import java.util.HashMap;
import java.util.Map;

public class ComputeExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("apple", 5);

        // 기존 값에 3을 더하기
        map.compute("apple", (key, value) -> (value == null) ? 1 : value + 3);
        System.out.println(map); // {apple=8}
        
        map.compute("banana", (key, value) -> (value == null) ? 1 : value + 3);
        System.out.println(map); // {apple=8, banana=1}
        
        map.compute("apple", (key, value) -> null);
        System.out.println(map); // {banana=1}
    }
}
  • compute()는 변경된 값을 반환한다.
  • remappingFunction이 null을 반환하면, 키가 삭제되고 compute()도 null을 반환한다.
import java.util.HashMap;
import java.util.Map;

public class ComputeReturnExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("apple", 5);

        // compute()의 반환값을 변수에 저장
        Integer newValue = map.compute("apple", (key, value) -> value + 3);
        System.out.println("변경된 값: " + newValue); // 8
        System.out.println("현재 map: " + map); // {apple=8}

        // 키를 삭제하는 경우
        Integer removedValue = map.compute("apple", (key, value) -> null);
        System.out.println("삭제된 후 반환값: " + removedValue); // null
        System.out.println("현재 map: " + map); // {}
    }
}

computeIfAbsent()

default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
  • computeIfAbsent : 제공된 키에 해당하는 값이 없으면 키를 이용해 새 값을 계산하고 Map에 추가하고 값을 반환,
    키가 존재하면 기존 값을 유지하고 반환
  • 키가 존재하고 값이 null이 아닌 경우 → 기존 값을 그대로 유지
  • 키가 없거나 값이 null인 경우 → mappingFunction을 실행하여 값을 계산한 후 저장
import java.util.HashMap;
import java.util.Map;

public class ComputeIfAbsentExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("apple", 5);

        // "apple" 키는 존재하므로 변경되지 않음
        map.computeIfAbsent("apple", key -> 10);
        
        // "banana" 키가 없으므로 새 값 7을 계산하여 추가
        map.computeIfAbsent("banana", key -> 7);

        System.out.println(map); // {apple=5, banana=7}
    }
}

리스트를 활용한 그룹화

import java.util.*;

public class ComputeIfAbsentListExample {
    public static void main(String[] args) {
        Map<String, List<String>> map = new HashMap<>();

        // "fruits" 키가 없으면 새 리스트를 생성 후 "apple" 추가
        map.computeIfAbsent("fruits", key -> new ArrayList<>()).add("apple");

        // "fruits" 키가 존재하므로 기존 리스트에 "banana" 추가
        map.computeIfAbsent("fruits", key -> new ArrayList<>()).add("banana");

        System.out.println(map); // {fruits=[apple, banana]}
    }
}

computeIfPresent()

default V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

 

  • 키가 존재하고 값이 null이 아닐 경우 → remappingFunction을 실행하여 값을 변경
  • 키가 없거나 값이 null일 경우 → 아무 동작도 하지 않음
  • remappingFunction이 null을 반환하면 → 해당 키를 HashMap에서 삭제
import java.util.HashMap;
import java.util.Map;

public class ComputeIfPresentExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("apple", 5);
        map.put("banana", null);

        // "apple" 키가 존재하므로 값을 변경 (5 + 3)
        map.computeIfPresent("apple", (key, value) -> value + 3);

        // "banana" 키는 있지만 값이 null이라 실행되지 않음
        map.computeIfPresent("banana", (key, value) -> 10);

        // "cherry" 키는 존재하지 않으므로 실행되지 않음
        map.computeIfPresent("cherry", (key, value) -> 20);

        System.out.println(map); // {apple=8, banana=null}
    }
}

값이 특정 조건을 만족할 때만 업데이트

import java.util.*;

public class ComputeIfPresentConditionExample {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("apple", 5);
        map.put("banana", 2);

        // 값이 3 이상이면 2배로 변경
        map.computeIfPresent("apple", (key, value) -> (value >= 3) ? value * 2 : value);

        // 값이 3 미만이면 변경되지 않음
        map.computeIfPresent("banana", (key, value) -> (value >= 3) ? value * 2 : value);

        System.out.println(map); // {apple=10, banana=2}
    }
}

삭제 패턴

map.remove("C");    //키가 존재하면 키를 삭제
System.out.println(map);    //{A=3}

map.remove("A", 2);     //값이 일치할 때 삭제
System.out.println(map);	//{A=3}

교체 패턴

map.replaceAll((k, v) -> v * v);    //키가 존재하면 값을 변경
System.out.println(map);    //{A=9}

Merge

두개의 Map에서 중복된 키가 없다면 putAll() 메서드로 가능

// 첫 번째 맵
Map<String, Integer> map1 = new HashMap<>();
map1.put("apple", 3);
map1.put("banana", 2);

// 두 번째 맵
Map<String, Integer> map2 = new HashMap<>();
map2.put("banana", 5); // 중복된 키 "banana"

// 중복된 키의 값을 덮어쓰기 위해 map2를 map1에 추가
map1.putAll(map2);

// 합쳐진 맵 출력
map1.forEach((key, value) -> System.out.println("Key: " + key + ", Value: " + value));	//banana=5

forEach와 merge 메서드를 이용해 충돌 해결

// 첫 번째 맵
Map<String, Integer> map1 = new HashMap<>();
map1.put("apple", 3);
map1.put("banana", 2);

// 두 번째 맵
Map<String, Integer> map2 = new HashMap<>();
map2.put("banana", 5); // 중복된 키 "banana"

// merge() 메서드를 사용하여 두 맵을 합침
map2.forEach((key, value) -> map1.merge(key, value, (oldValue, newValue) -> oldValue + newValue));

// 합쳐진 맵 출력
map1.forEach((key, value) -> System.out.println("Key: " + key + ", Value: " + value));	//banana=7

초기화 검사는 특정 키가 맵에 없을 때 초기값을 설정하고, 이미 존재하는 경우에는 값을 누적하거나 다른 동작을 수행

Map<String, Integer> map = new HashMap<>();
map.put("apple", 3);
map.put("banana", 2);

// 특정 키에 대한 값을 누적하는 예제
String key = "banana";
int incrementValue = 5; // 누적할 값

// merge() 메서드를 사용하여 초기화 검사 수행
map.merge(key, incrementValue, (oldValue, newValue) -> oldValue + newValue);

// 결과 출력
map.forEach((k, v) -> System.out.println("Key: " + k + ", Value: " + v));	//banana=7
728x90
반응형
반응형
300x250